			/* ------------------------------------- */
			//										 //
			//  +-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+  //
			//  |S|i|m|p|l|e| |P|r|o|x|y| |2|0|0|4|  //
			//  +-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+  //
			//										 //
			//										 //
			//  AUTOR : Aymeric  //
			//  DATE  : May 2004					 //
			//  FILE  : getPage.c					 //
			//  DESC  : functions to get the page    //
			//          from the web server			 //
			//  									 //
			/* ------------------------------------- */


/************************************************************************/

#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include "proxy.h"

/************************************************************************/
// FunctionName : getPage
//
// Description  : send the request HTTP message to the http server.
//				  get the page from the server and send it to execute()
//
// Parameters
// [in]
//			char *buf			  : the request message to send
//			struct sConfig config : used to proxy hostname/port
//			int csock			  : current socket
//			char *url			  : url asked
//			struct sLog alog	  : to pass to execute()
//
// [out]
//			nothing
//
// Returns
//			bool : return what execute() return. True if OK
//
// Calls
//			getDetailsURI() : used to find the host and port to the
//							  the HTTP server
//			clearRequete()  : remove some lines in the message to send
//			changeRequete() : change the first line request
//
// Globals
//			FILE *log	 	 : file id for the general log
//			enum bool debug	 : if debug is true, we are in debug mode
//
/************************************************************************/

enum bool getPage(char *buf, struct sConfig config, int csock, char *url, struct sLog alog)
{
	int psock,toport;
	struct sockaddr_in sin;
	struct sockaddr_in csin;
	struct hostent *host_ent;
	char *buffer,*connectto;
	int temp,n=0,length,sinsize;
	struct headerHTTP hHTTP;

	/* if we use a proxyserv before connecting to the Internet */
	if (config.proxyserv == 1)
	{
		connectto=(char *)calloc(sizeof(char),strlen(config.proxyhost)+1);
		strcpy(connectto,config.proxyhost);
		toport=config.proxyport;
		if (debug) printf("[getPage] Connected to HostProxy (%s) on port %d\n",connectto,toport);
	}
	else
	{
		/* we find the serv adress and port with the url */
		char *tmp;
		tmp=(char *)calloc(sizeof(char),strlen(url)+1+7);
		strcpy(tmp,"http://");
		strcat(tmp,url);
		if (debug) printf("[getPage] tmp = %s et url = %s\n",tmp,url);

		getDetailsURI(&hHTTP,tmp);
		free(tmp);

		connectto=(char *)calloc(sizeof(char),strlen(hHTTP.URIserv)+1);
		strcpy(connectto,hHTTP.URIserv);
		toport=hHTTP.URIport;
		if (debug) printf("[getPage] Connected to Host (%s) on port %d\n",connectto,toport);
	}

	if ( (sin.sin_addr.s_addr = inet_addr(connectto)) == -1 )
	{
		host_ent = gethostbyname(connectto);
		if (debug) printf("[getPage] hots_ent = %s\n",host_ent);
		if (host_ent == NULL)
		{
			if (debug) printf("[getPage] Unable to resolve hostname %s\n",connectto);
			else
			{
				fprintf(log,"[%s] Unable to resolve server hostname (%s)\n",logtime(),connectto);
				fflush(log);
			}
			exit(-1);
		}
		memcpy ((char *)&sin.sin_addr,host_ent->h_addr_list[0],host_ent->h_length);
	}

	sin.sin_family				= AF_INET;
	sin.sin_port				= htons(toport);
	memset(&(sin.sin_zero), '\0', 8);

	psock = socket(AF_INET, SOCK_STREAM, 0);

	if (psock == -1)
	{
		fprintf(log,"[%s] Bad Socket (getPage)\n",logtime());
		fflush(log);
		perror("SOCKET");
	}

	if (debug) printf("[getPage] Socket -> OK !\n");

	sinsize=sizeof(sin);

	/* connection to the web server */
	if ( connect(psock, (struct sockaddr *)&sin, sinsize) != 0 )
	{
		if (debug) printf("[getPage] Unable to connect to %s",connectto);
	}

	if (debug) printf("[getPage] Connected to %s -> OK !\n",connectto);

	//#ifndef __linux__
	//	strncpy(buf,clearRequete(buf),strlen(buf));
	//#endif
	if (config.proxyserv == 0)
		strncpy(buf,changeRequete(buf,hHTTP),strlen(buf));

	//if (debug) printf("[getPage] MESSAGE SENT :\n%s\n",buf);

	/* send the request */
	if ( write(psock,buf,strlen(buf)) == -1 )
	{
		if (debug) printf("[getPage] Bad Write\n");
		perror("write");
		close(psock);
	}


	/* reception of the web page */
	buffer=(char *)calloc(BUFFERSIZE,8);
	length=BUFFERSIZE*8;

	/* we use several read() because read receive only 1 packet */
	temp=read(psock,buffer,sizeof(buffer)-1);
	if ( temp == -1 )
		perror("READ");

	n=temp;

	while ( temp > 0 )
	{
		temp=read(psock,buffer+n,sizeof(buffer)-1);
		if ( temp == -1 )
			perror("READ");

		n += temp;

		if ( n >= length )
		{
			(char *)realloc(buffer,n*2);
			length=n*2;
			if (debug) printf("[getPage] Realloc memory for buffer (%d)\n",length);
		}
	}

	/* we close the communication with the server */
	shutdown(psock,2);
	close(psock);

	getEntityHeader(&hHTTP, buffer);
	if (debug) printf("[getPage] ContentLength = %d\n",hHTTP.ContentLength);

	if (debug) printf("[getPage] Length of content = %d\n",length);

	return execute(buffer,csock,url,n,config,&alog);
}

/************************************************************************/
// FunctionName : clearRequete
//
// Description  : remove inappropriate header lines
//
// Parameters
// [in]
//			char *str : the message
//
// [out]
//			nothing
//
// Returns
//			char* : the message without inappropriate header lines
//
// Calls
//			nothing
//
// Globals
//			enum bool debug	 : if debug is true, we are in debug mode
//
/************************************************************************/

char *clearRequete(char *str)
{
	char *str1=NULL,*svg;
	char *str2="Proxy-Connection:", *ptr, *str3="Keep-Alive\r\n";
	char *cookie;
	char *HTTPversion;
	char *result;
	int debut,fin,i,j=0;

	/* We remove Proxy-Connect: Keep-Alive because it creates problems */
	if (debug) printf("[clearRequete] Clear of Proxy-Connect -> ?? !\n");
	ptr = strstr(str, str2);
	if ( ptr != NULL )
	{
		debut=ptr-str;
		ptr = strstr(str, str3);
		fin=ptr-str+strlen(str3)-1;
		str1=(char *)calloc(sizeof(char),strlen(str)-(fin-debut)+1);

		for (i=0; i < strlen(str); i++)
		{
			if ( i < debut || i > fin )
				str1[j++]=str[i];
		}
		if (debug) printf("[clearRequete] Clear of Proxy-Connect -> OK !\n");
	}

	if ( str1 != NULL )
	{
		svg=(char *)malloc(strlen(str1)+1);
		strcpy(svg,str1);
	}
	else
	{
		svg=(char *)malloc(strlen(str)+1);
		strcpy(svg,str);
		str1=(char *)malloc(strlen(str)+1);
		strcpy(str1,str);
	}

	HTTPversion = strtok(str1, " \r\n");
	i=0;

	/* we transform the HTTP/1.1 in HTTP/1.0 */
	if (debug) printf("[clearRequete] Clear of HTTP/1.1 -> ?? !\n");
	while ( HTTPversion != NULL )
	{
		if ( strcmp(HTTPversion,"HTTP/1.1") == 0 )
		{
			i=HTTPversion-str1;
			break;
		}
		HTTPversion = strtok(NULL, " \r\n");
	}
	if ( i != 0 )
	{
		i+=7;
		svg[i]='0';
		if (debug) printf("[clearRequete] Clear of HTTP/1.1 -> OK !\n");
	}

	return(svg);
}


/************************************************************************/
// FunctionName : changeRequete
//
// Description  : we need to change tue URI when we have a direct
//				  connection to the web server
//
// Parameters
// [in]
//			char *str			: the message
//			struct headerHTTP H : to change with the correct params
//
// [out]
//			nothing
//
// Returns
//			char*	: the new message modified
//
// Calls
//			nothing
//
// Globals
//			enum bool debug	 : if debug is true, we are in debug mode
//
/************************************************************************/

char *changeRequete(char *str, struct headerHTTP H)
{
	char *str1,*ptr;
	int debut,fin,i,j,k;

	if (debug) printf("[changeRequete] Changing the URI...\n");
	ptr = strstr(str, " ");

	debut=ptr-str;

	ptr = strstr(str, " HTTP");
	fin=ptr-str;

	str1=(char *)calloc(sizeof(char),strlen(str)-(fin-debut)+strlen(H.URIpath)+1);

	for (i=0,j=0; i < strlen(str); i++)
	{
		if ( i < debut || i > fin )
			str1[j++]=str[i];
		else
		{
			str1[j++]=' ';
			for (k=0;k < strlen(H.URIpath); k++)
				str1[j++]=H.URIpath[k];
			str1[j++]=' ';
			i=fin;
		}
	}

	if (debug) printf("[changeRequete] Changing finished !\n");
	return(str1);
}
