			/* ------------------------------------- */
			//										 //
			//  +-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+  //
			//  |S|i|m|p|l|e| |P|r|o|x|y| |2|0|0|4|  //
			//  +-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+  //
			//										 //
			//										 //
			//  AUTOR : Aymeric  //
			//  DATE  : May 2004					 //
			//  FILE  : cacheFiles.c				 //
			//  DESC  : operations on the file about //
			//          the proxy's cache			 //
			//  									 //
			/* ------------------------------------- */


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

#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 : checkCache
//
// Description  : check if the page is in the cache (into the index file)
//
// Parameters
// [in]
//			char* url		 : url that we can search
//			struct sCache *C : used to set members of the structure
//
// [out]
//			struct sCache *C : file's name, Freshness, last_access, url
//
// Returns
//			enum bool : true if all is ok.
//
// Calls
//			logtime() : for the timestamps in the log file
//
// Globals
//			FILE *log	 	 : file id for the general log
//			enum bool debug	 : if debug is true, we are in debug mode
//
/************************************************************************/

enum bool checkCache(char *url, struct sCache *C)
{
	FILE *index;
	time_t current;
	char line[BUFFERSIZE*2]="";
	char *ptr;

	current = time(NULL);

	index=fopen(INDEXFILE,"r");

	if ( index == NULL )
	{
		if (debug) printf("[saveCache] %s doesn't exist anymore ?!\n",INDEXFILE);
		else
		{
			fprintf(log,"[%s] [saveCache] %s doesn't exist anymore ?!\n",logtime(),INDEXFILE);
			fflush(log);
		}
		exit(0);
	}

	/* we read the file from the beggining */
	while(fgets(line, sizeof(line) - 1, index) != NULL)
	{
		ptr=strtok(line," \r\n");

		if ( ptr == NULL )
		{
			if (debug) printf("[checkCache] The indexfile is empty.\n");
			return(false);
		}

		if (strcmp(ptr,url) == 0)
		{
			ptr=strtok(NULL," ");
			if ( ptr == NULL )
			{
				fclose(index);
				return(false);
			}

			C->file=(char *)calloc(sizeof(char),strlen(ptr)+1);
			strcpy(C->file,ptr);

			if (debug) printf("[checkCache] File => %s -> OK !\n",C->file);

			ptr=strtok(NULL," ");
			if ( ptr == NULL )
			{
				fclose(index);
				return(false);
			}

			/* if the date has expired, we don't use the cache file */
			if ( (current > atoi(ptr)) && (C->cache == false) )
			{
				if (debug) printf("[checkCache] %s has expired.\n",url);
				fclose(index);
				return(false);
			}

			if ( C->cache == false ) C->freshness=atoi(ptr);

			if (debug) printf("[checkCache] Freshness => %s",ctime(&C->freshness));

			ptr=strtok(NULL,"\r\n");
			if ( ptr == NULL )
			{
				fclose(index);
				return(false);
			}

			C->last_access=atoi(ptr);

			if (debug) printf("[checkCache] Last access => %s",ctime(&C->last_access));

			fclose(index);
			return(true);
		}
	}
	fclose(index);
	return(false);
}


/************************************************************************/
// FunctionName : saveCache
//
// Description  : save in the index file a new line
//
// Parameters
// [in]
//			struct sCache *C : used to set the new line
//
// [out]
//			nothing
//
// Returns
//			nothing
//
// Calls
//			logtime() : for the timestamps in the log file
//
// Globals
//			FILE *log	 	 : file id for the general log
//			enum bool debug	 : if debug is true, we are in debug mode
//
/************************************************************************/

void saveCache(struct sCache *C)
{
	FILE *index;
	char *line;
	char str[10],truc[30],axx[20];
	char s[BUFFERSIZE*2];
	int i=line_count(INDEXFILE);
	time_t temps_act;

	C->last_access=time(&temps_act);

	if (i == -1)
	{
		if (debug) printf("[saveCache] %s doesn't exist anymore ?!\n",INDEXFILE);
		else
		{
			fprintf(log,"[%s] [saveCache] %s doesn't exist anymore ?!\n",logtime(),INDEXFILE);
			fflush(log);
		}
		exit(0);
	}

	C->file=(char *)calloc(sizeof(char),sprintf(truc,"C%d%d.pro",time(&temps_act),getpid())+1);
	strcpy(C->file,truc);

	line=(char *)calloc(sizeof(char),strlen(C->url)+1+strlen(C->file)+1+sprintf(str,"%d",C->freshness)+1+sprintf(axx,"%d",C->last_access)+2);
	strcpy(line,C->url);
	strcat(line," ");
	strcat(line,C->file);
	strcat(line," ");
	strcat(line,str);
	strcat(line," ");
	strcat(line,axx);
	strcat(line,"\r\n");

	/* access by the end of the index file */
	index=fopen(INDEXFILE,"a+");

	fputs(line,index);

	fclose(index);

	free(line);
}

/************************************************************************/
// FunctionName : fileCache
//
// Description  : write the buffer in a file
//
// Parameters
// [in]
//			char *cfile  : name of the cached file
//			char *buffer : contains the request page that go to be cached
//			int n 		 : size of the buffer
//
// [out]
//			nothing
//
// Returns
//			nothing
//
// Calls
//			logtime() : for the timestamps in the log file
//
// Globals
//			FILE *log	 	 : file id for the general log
//			enum bool debug	 : if debug is true, we are in debug mode
//
/************************************************************************/

void fileCache(char *cfile, char *buffer, int n)
{
	FILE *F;
	long i=0;
	char *file;

	file=(char*)calloc(sizeof(char),strlen(cfile)+strlen(CACHEDIR)+1);
	strcpy(file,CACHEDIR);
	strcat(file,cfile);

	if (debug) printf("[fileCache] Opening file %s\n",file);

	/* open stream in creation/write */
	F=fopen(file,"wb+");

	if (F == NULL)
	{
		if (debug) printf("[fileCache] Unable to open %s\n",file);
		else
		{
			fprintf(log,"[%s] Unable to open %s\n",logtime(),file);
			fflush(log);
		}
		exit(0);
	}

	while( i < (n-1) )
	{
		/* we write characters one by one to not have problems with the '\0' */
		fputc(buffer[i],F);
		i++;
	}

	if (debug) printf("[fileCache] Closing file %s\n",file);
	fclose(F);
}

/************************************************************************/
// FunctionName : readCache
//
// Description  : read the cached file to send it to the client
//
// Parameters
// [in]
//			char *file : name of the file to read
//			int size   : size of the file
//
// [out]
//			nothing
//
// Returns
//			char* : message for the client (content of the file or error)
//
// Calls
//			logtime() : for the timestamps in the log file
//
// Globals
//			FILE *log	 	 : file id for the general log
//			enum bool debug	 : if debug is true, we are in debug mode
//
/************************************************************************/

char *readFile(char *file, int size)
{
	char *tempbuf;
	int i=0;
	FILE *fp;
	char car;

	tempbuf=(char *)calloc(sizeof(char),size);

	/* we open the stream in read */
	fp = fopen(file, "r");

	if ( fp == NULL )
	{
		if (debug) printf("[readFile] Unable to open %s\n",file);
		else
		{
			fprintf(log,"[%s] Unable to open %s - Where is this cache file ?!\n",logtime(),file);
			fflush(log);
		}
		/* A CHANGER */
		return("Impossible to read cache file !");
	}

	car=(char)fgetc(fp);

	while(!feof(fp))
	{
		/* we read character by character to avoid problems with '\0' */
		tempbuf[i]=car;
		car=(char)fgetc(fp);
		i++;
	}

	fclose(fp);

	return tempbuf;
}


/************************************************************************/
// FunctionName : changeCache
//
// Description  : modify the right line in index file with the new param
//
// Parameters
// [in]
//			struct sCache C : used to define the new line to write
//
// [out]
//			nothing
//
// Returns
//			nothing
//
// Calls
//			logtime() : for the timestamps in the log file
//
// Globals
//			FILE *log	 	 : file id for the general log
//			enum bool debug	 : if debug is true, we are in debug mode
//
/************************************************************************/

void changeCache(struct sCache C)
{
	FILE *index;
	char line[512]="",linec[512]="";
	long curpos;
	char *ptr;

	index=fopen(INDEXFILE,"r+");

	if ( index == NULL )
	{
		if (debug) printf("[changeCache] Enable to open %s ?!\n",INDEXFILE);
		else
		{
			fprintf(log,"[%s] Unable to open %s ?!\n",logtime(),INDEXFILE);
			fflush(log);
		}
		exit(0);
	}

	/* we move the cursor in the file where we want and we change the line */
	rewind(index);
	curpos = ftell(index);

	while(!feof(index))
	{
		if ( fgets(line, sizeof(line) - 1, index) == NULL ) break;

		ptr=strtok(line," ");
		if ( ptr == NULL ) return;
		if (strcmp(ptr,C.url) == 0)
		{
			int i;

			fseek(index, curpos, SEEK_SET);
			sprintf(linec,"%s %s %d %d",C.url,C.file,C.freshness,C.last_access);
			fputs(linec,index);
			break;
		}
		curpos = ftell(index);
	}
	fclose(index);

}


/************************************************************************/
// FunctionName : line_count
//
// Description  : Count the number of line in a file and return number
//
// Parameters
// [in]
//			char *filename : name of the file to read
//
// [out]
//			nothing
//
// Returns
//			int : number of line (-1 if error)
//
// Calls
//			nothing
//
// Globals
//			none
//
/************************************************************************/

int line_count(char *filename)
{
	char tempbuf[BUFFERSIZE*2+1];
	int  line = 0;
	FILE *fp;

	fp = fopen(filename, "r+");			/* To get the num of line */

	if(!fp) {
		return -1;
	}
	while(fgets(tempbuf, BUFFERSIZE*2, fp)) {
		line++;
	}

	fclose(fp);
	return line;
}

/************************************************************************/
// FunctionName : char_count
//
// Description  : Count the number of characters in a file and return number
//
// Parameters
// [in]
//			char *filename : name of the file to read
//
// [out]
//			nothing
//
// Returns
//			int : number of character (-1 if error)
//
// Calls
//			nothing
//
// Globals
//			none
//
/************************************************************************/

int char_count(char *filename)
{
	char temp;
	int  car = 0;
	FILE *fp;

	fp = fopen(filename, "r+");

	if(!fp) {
		return -1;
	}
	while(!feof(fp))
	{
		temp = fgetc(fp);
		car++;
	}

	fclose(fp);
	return car;
}
