diff options
author | Xavier Roche <xroche@users.noreply.github.com> | 2012-03-19 12:36:11 +0000 |
---|---|---|
committer | Xavier Roche <xroche@users.noreply.github.com> | 2012-03-19 12:36:11 +0000 |
commit | ad5b7acc19290ff91e0f42a0de448a26760fcf99 (patch) | |
tree | 2d1867758835fd0c4e443ff3cc7e5c774af85874 /src/htscache.c |
Imported httrack 3.20.2
Diffstat (limited to 'src/htscache.c')
-rw-r--r-- | src/htscache.c | 881 |
1 files changed, 881 insertions, 0 deletions
diff --git a/src/htscache.c b/src/htscache.c new file mode 100644 index 0000000..da8791e --- /dev/null +++ b/src/htscache.c @@ -0,0 +1,881 @@ +/* ------------------------------------------------------------ */ +/* +HTTrack Website Copier, Offline Browser for Windows and Unix +Copyright (C) Xavier Roche and other contributors + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +Important notes: + +- We hereby ask people using this source NOT to use it in purpose of grabbing +emails addresses, or collecting any other private information on persons. +This would disgrace our work, and spoil the many hours we spent on it. + + +Please visit our Website: http://www.httrack.com +*/ + + +/* ------------------------------------------------------------ */ +/* File: httrack.c subroutines: */ +/* cache system (index and stores files in cache) */ +/* Author: Xavier Roche */ +/* ------------------------------------------------------------ */ + +#include "htscache.h" + +/* specific definitions */ +#include "htsbase.h" +#include "htsbasenet.h" +#include "htsmd5.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "htsnostatic.h" +/* END specific definitions */ + +#undef test_flush +#define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); } + +// routines de mise en cache + +/* + VERSION 1.0 : + ----------- + +.ndx file + file with data + <string>(date/time) [ <string>(hostname+filename) (datfile_position_ascii) ] * number_of_links + file without data + <string>(date/time) [ <string>(hostname+filename) (-datfile_position_ascii) ] * number_of_links + +.dat file + [ file ] * +with + file= (with data) + [ bytes ] * sizeof(htsblk header) [ bytes ] * n(length of file given in htsblk header) + file= (without data) + [ bytes ] * sizeof(htsblk header) +with + <string>(name) = <length in ascii>+<lf>+<data> + + + VERSION 1.1/1.2 : + --------------- + +.ndx file + file with data + <string>("CACHE-1.1") <string>(date/time) [ <string>(hostname+filename) (datfile_position_ascii) ] * number_of_links + file without data + <string>("CACHE-1.1") <string>(date/time) [ <string>(hostname+filename) (-datfile_position_ascii) ] * number_of_links + +.dat file + <string>("CACHE-1.1") [ [Header_1.1] [bytes] * n(length of file given in header) ] * +with + Header_1.1= + <int>(statuscode) + <int>(size) + <string>(msg) + <string>(contenttype) + <string>(last-modified) + <string>(Etag) + [<string>"SD" <string>(supplemental data)] + [<string>"SD" <string>(supplemental data)] + ... + <string>"HTS" (end of header) + <int>(number of bytes of data) (0 if no data written) +*/ + +// Nouveau: si != text/html ne stocke que la taille + + +void cache_mayadd(httrackp* opt,cache_back* cache,htsblk* r,char* url_adr,char* url_fil,char* url_save) { + if ((opt->debug>0) && (opt->log!=NULL)) { + fspc(opt->log,"debug"); fprintf(opt->log,"File checked by cache: %s"LF,url_adr); + } + // ---stockage en cache--- + // stocker dans le cache? + if (opt->cache) { + if (cache->dat!=NULL) { + // c'est le seul endroit ou l'on ajoute des elements dans le cache (fichier entier ou header) + // on stocke tout fichier "ok", mais également les réponses 404,301,302... + if ((r->statuscode==200) /* stocker réponse standard, plus */ + || (r->statuscode==204) /* no content */ + || (r->statuscode==301) /* moved perm */ + || (r->statuscode==302) /* moved temp */ + || (r->statuscode==303) /* moved temp */ + || (r->statuscode==307) /* moved temp */ + || (r->statuscode==401) /* authorization */ + || (r->statuscode==403) /* unauthorized */ + || (r->statuscode==404) /* not found */ + || (r->statuscode==410) /* gone */ + ) + { /* ne pas stocker si la page générée est une erreur */ + if (!r->is_file) { + // stocker fichiers (et robots.txt) + if ( (strnotempty(url_save)) || (strcmp(url_fil,"/robots.txt")==0)) { + // ajouter le fichier au cache + cache_add(*r,url_adr,url_fil,url_save,cache->ndx,cache->dat,opt->all_in_cache); + } + } + } + } + } + // ---fin stockage en cache--- +} + + +/* Ajout d'un fichier en cache */ +void cache_add(htsblk r,char* url_adr,char* url_fil,char* url_save,FILE* cache_ndx,FILE* cache_dat,int all_in_cache) { + int pos; + char s[256]; + char buff[HTS_URLMAXSIZE*4]; + int ok=1; + int dataincache=0; // donnée en cache? + /*char digest[32+2];*/ + /*digest[0]='\0';*/ + + // Longueur url_save==0? + if ( (strnotempty(url_save)==0) ) { + if (strcmp(url_fil,"/robots.txt")==0) // robots.txt + dataincache=1; + else + return; // erreur (sauf robots.txt) + } + + if (r.size <= 0) // taille <= 0 + return; // refusé.. + + // Mettre les *donées* en cache ? + if (is_hypertext_mime(r.contenttype)) // html, mise en cache des données et + dataincache=1; // pas uniquement de l'en tête + else if (all_in_cache) + dataincache=1; // forcer tout en cache + + /* calcul md5 ? */ + /* + if (is_hypertext_mime(r.contenttype)) { // html, calcul MD5 + if (r.adr) { + domd5mem(r.adr,r.size,digest,1); + } + }*/ + + // Position + fflush(cache_dat); fflush(cache_ndx); + pos=ftell(cache_dat); + // écrire pointeur seek, adresse, fichier + if (dataincache) // patcher + sprintf(s,"%d\n",pos); // ecrire tel que (eh oui évite les \0..) + else + sprintf(s,"%d\n",-pos); // ecrire tel que (eh oui évite les \0..) + + // data + // écrire données en-tête, données fichier + /*if (!dataincache) { // patcher + r.size=-r.size; // négatif + }*/ + + // Construction header + ok=0; + if (cache_wint(cache_dat,r.statuscode)!=-1) // statuscode + if (cache_wLLint(cache_dat,r.size)!=-1) // size + if (cache_wstr(cache_dat,r.msg)!=-1) // msg + if (cache_wstr(cache_dat,r.contenttype)!=-1) // contenttype + if (cache_wstr(cache_dat,r.lastmodified)!=-1) // last-modified + if (cache_wstr(cache_dat,r.etag)!=-1) // Etag + if (cache_wstr(cache_dat,(r.location!=NULL)?r.location:"")!=-1) // 'location' pour moved + if (cache_wstr(cache_dat,r.cdispo)!=-1) // Content-disposition + if (cache_wstr(cache_dat,"HTS")!=-1) // end of header + ok=1; /* ok */ + // Fin construction header + + /*if ((int) fwrite((char*) &r,1,sizeof(htsblk),cache_dat) == sizeof(htsblk)) {*/ + if (ok) { + if (dataincache) { // mise en cache? + if (!r.adr) { /* taille nulle (parfois en cas de 301 */ + if (cache_wLLint(cache_dat,0)==-1) /* 0 bytes */ + ok=0; + } else if (r.is_write==0) { // en mémoire, recopie directe + if (cache_wLLint(cache_dat,r.size)!=-1) { + if (r.size>0) { // taille>0 + if ((INTsys) fwrite(r.adr,1,(INTsys)r.size,cache_dat)!=r.size) + ok=0; + } else // taille=0, ne rien écrire + ok=0; + } else + ok=0; + } else { // recopier fichier dans cache + FILE* fp; + // On recopie le fichier.. + LLint file_size=fsize(fconv(url_save)); + if (file_size>=0) { + if (cache_wLLint(cache_dat,file_size)!=-1) { + fp=fopen(fconv(url_save),"rb"); + if (fp!=NULL) { + char buff[32768]; + int nl; + do { + nl=fread(buff,1,32768,fp); + if (nl>0) { + if ((INTsys) fwrite(buff,1,(INTsys)nl,cache_dat)!=nl) { // erreur + nl=-1; + ok=0; + } + } + } while(nl>0); + fclose(fp); + } else ok=0; + } else ok=0; + } else ok=0; + } + } else { + if (cache_wLLint(cache_dat,0)==-1) /* 0 bytes */ + ok=0; + } + } else ok=0; + /*if (!dataincache) { // dépatcher + r.size=-r.size; + }*/ + + // index + // adresse+cr+fichier+cr + if (ok) { + buff[0]='\0'; strcat(buff,url_adr); strcat(buff,"\n"); strcat(buff,url_fil); strcat(buff,"\n"); + cache_wstr(cache_ndx,buff); + fwrite(s,1,strlen(s),cache_ndx); + } // si ok=0 on a peut être écrit des données pour rien mais on s'en tape + + // en cas de plantage, on aura au moins le cache! + fflush(cache_dat); fflush(cache_ndx); +} + + +// lecture d'un fichier dans le cache +// si save==null alors test unqiquement +htsblk cache_read(httrackp* opt,cache_back* cache,char* adr,char* fil,char* save) { +#if HTS_FAST_CACHE + long int hash_pos; + int hash_pos_return; +#else + char* a; +#endif + char buff[HTS_URLMAXSIZE*2]; + char location[HTS_URLMAXSIZE*2]; + htsblk r; + int ok=0; + int header_only=0; + + memset(&r, 0, sizeof(htsblk)); r.soc=INVALID_SOCKET; strcpy(location,""); r.location=location; +#if HTS_FAST_CACHE + strcpy(buff,adr); strcat(buff,fil); + hash_pos_return=inthash_read((inthash)cache->hashtable,buff,(long int*)&hash_pos); +#else + buff[0]='\0'; strcat(buff,"\n"); strcat(buff,adr); strcat(buff,"\n"); strcat(buff,fil); strcat(buff,"\n"); + if (cache->use) + a=strstr(cache->use,buff); + else + a=NULL; // forcer erreur +#endif + + // en cas de succès +#if HTS_FAST_CACHE + if (hash_pos_return) { +#else + if (a!=NULL) { // OK existe en cache! +#endif + int pos; +#if DEBUGCA + fprintf(stdout,"..cache: %s%s at ",adr,fil); +#endif + +#if HTS_FAST_CACHE + pos=hash_pos; /* simply */ +#else + a+=strlen(buff); + sscanf(a,"%d",&pos); // lire position +#endif +#if DEBUGCA + printf("%d\n",pos); +#endif + + fflush(cache->olddat); + if (fseek(cache->olddat,((pos>0)?pos:(-pos)),SEEK_SET) == 0) { + /* Importer cache1.0 */ + if (cache->version==0) { + OLD_htsblk old_r; + if (fread((char*) &old_r,1,sizeof(old_r),cache->olddat)==sizeof(old_r)) { // lire tout (y compris statuscode etc) + r.statuscode=old_r.statuscode; + r.size=old_r.size; // taille fichier + strcpy(r.msg,old_r.msg); + strcpy(r.contenttype,old_r.contenttype); + ok=1; /* import ok */ + } + /* */ + /* Cache 1.1 */ + } else { + char check[256]; + LLint size_read; + check[0]='\0'; + // + cache_rint(cache->olddat,&r.statuscode); + cache_rLLint(cache->olddat,&r.size); + cache_rstr(cache->olddat,r.msg); + cache_rstr(cache->olddat,r.contenttype); + cache_rstr(cache->olddat,r.lastmodified); + cache_rstr(cache->olddat,r.etag); + cache_rstr(cache->olddat,r.location); + if (cache->version >= 2) + cache_rstr(cache->olddat,r.cdispo); + // + cache_rstr(cache->olddat,check); + if (strcmp(check,"HTS")==0) { /* intégrité OK */ + ok=1; + } + cache_rLLint(cache->olddat,&size_read); /* lire size pour être sûr de la taille déclarée (réécrire) */ + if (size_read>0) { /* si inscrite ici */ + r.size=size_read; + } else { /* pas de données directement dans le cache, fichier présent? */ + if (r.statuscode!=200) + header_only=1; /* que l'en tête ici! */ + } + } + + /* Remplir certains champs */ + r.totalsize=r.size; + + // lecture du header (y compris le statuscode) + /*if (fread((char*) &r,1,sizeof(htsblk),cache->olddat)==sizeof(htsblk)) { // lire tout (y compris statuscode etc)*/ + if (ok) { + // sécurité + r.adr=NULL; + r.out=NULL; + ////r.location=NULL; non, fixée lors des 301 ou 302 + r.fp=NULL; + + if ( (r.statuscode>=0) && (r.statuscode<=999) + && (r.notmodified>=0) && (r.notmodified<=9) ) { // petite vérif intégrité + if ((save) && (!header_only) ) { /* ne pas lire uniquement header */ + //int to_file=0; + + r.adr=NULL; r.soc=INVALID_SOCKET; + // // r.location=NULL; + +#if HTS_DIRECTDISK + // Court-circuit: + // Peut-on stocker le fichier directement sur disque? + if ((r.statuscode==200) && (!is_hypertext_mime(r.contenttype)) && (strnotempty(save))) { // pas HTML, écrire sur disk directement + int ok=0; + + r.is_write=1; // écrire + if (fexist(antislash(save))) { // un fichier existe déja + //if (fsize(antislash(save))==r.size) { // même taille -- NON tant pis (taille mal declaree) + ok=1; // plus rien à faire + filenote(save,NULL); // noter comme connu + //} + } + + if ((pos<0) && (!ok)) { // Pas de donnée en cache et fichier introuvable : erreur! + if (opt->norecatch) { + filecreateempty(save); + // + r.statuscode=-1; + strcpy(r.msg,"File deleted by user not recaught"); + ok=1; // ne pas récupérer (et pas d'erreur) + } else { + r.statuscode=-1; + strcpy(r.msg,"Previous cache file not found"); + ok=1; // ne pas récupérer + } + } + + if (!ok) { + r.out=filecreate(save); +#if HDEBUG + printf("direct-disk: %s\n",save); +#endif + if (r.out!=NULL) { + char buff[32768+4]; + LLint nl; + LLint size; + size=r.size; + do { + nl=fread(buff,1,(INTsys) minimum(size,32768),cache->olddat); + if (nl>0) { + size-=nl; + if ((INTsys) fwrite(buff,1,(INTsys)nl,r.out)!=nl) { // erreur + r.statuscode=-1; + strcpy(r.msg,"Cache Read Error : Read To Disk"); + } + } + } while((nl>0) && (size>0) && (r.statuscode!=-1)); + + fclose(r.out); + r.out=NULL; +#if HTS_WIN==0 + chmod(save,HTS_ACCESS_FILE); +#endif + usercommand(0,NULL,antislash(save)); + } else { + r.statuscode=-1; + strcpy(r.msg,"Cache Write Error : Unable to Create File"); + //printf("%s\n",save); + } + } + + } else +#endif + { // lire en mémoire + + if (pos<0) { // Pas de donnée en cache, bizarre car html!!! + r.statuscode=-1; + strcpy(r.msg,"Previous cache file not found (2)"); + } else { + // lire fichier (d'un coup) + r.adr=(char*) malloct((INTsys)r.size+4); + if (r.adr!=NULL) { + if ((INTsys) fread(r.adr,1,(INTsys)r.size,cache->olddat)!=r.size) { // erreur + freet(r.adr); + r.adr=NULL; + r.statuscode=-1; + strcpy(r.msg,"Cache Read Error : Read Data"); + } else + *(r.adr+r.size)='\0'; + //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode); + } else { // erreur + r.statuscode=-1; + strcpy(r.msg,"Cache Memory Error"); + } + } + } + } // si save==null, ne rien charger (juste en tête) + } else { +#if DEBUGCA + printf("Cache Read Error : Bad Data"); +#endif + r.statuscode=-1; + strcpy(r.msg,"Cache Read Error : Bad Data"); + } + } else { // erreur +#if DEBUGCA + printf("Cache Read Error : Read Header"); +#endif + r.statuscode=-1; + strcpy(r.msg,"Cache Read Error : Read Header"); + } + } else { +#if DEBUGCA + printf("Cache Read Error : Seek Failed"); +#endif + r.statuscode=-1; + strcpy(r.msg,"Cache Read Error : Seek Failed"); + } + } else { +#if DEBUGCA + printf("File Cache Not Found"); +#endif + r.statuscode=-1; + strcpy(r.msg,"File Cache Not Found"); + } + return r; +} + +/* write (string1-string2)-data in cache */ +/* 0 if failed */ +int cache_writedata(FILE* cache_ndx,FILE* cache_dat,char* str1,char* str2,char* outbuff,int len) { + if (cache_dat) { + char buff[HTS_URLMAXSIZE*4]; + char s[256]; + int pos; + fflush(cache_dat); fflush(cache_ndx); + pos=ftell(cache_dat); + /* first write data */ + if (cache_wint(cache_dat,len)!=-1) { // length + if ((INTsys) fwrite(outbuff,1,(INTsys)len,cache_dat) == (INTsys) len) { // data + /* then write index */ + sprintf(s,"%d\n",pos); + buff[0]='\0'; strcat(buff,str1); strcat(buff,"\n"); strcat(buff,str2); strcat(buff,"\n"); + cache_wstr(cache_ndx,buff); + if (fwrite(s,1,strlen(s),cache_ndx) == strlen(s)) { + fflush(cache_dat); fflush(cache_ndx); + return 1; + } + } + } + } + return 0; +} + +/* read the data corresponding to (string1-string2) in cache */ +/* 0 if failed */ +int cache_readdata(cache_back* cache,char* str1,char* str2,char** inbuff,int* inlen) { +#if HTS_FAST_CACHE + if (cache->hashtable) { + char buff[HTS_URLMAXSIZE*4]; + long int pos; + strcpy(buff,str1); strcat(buff,str2); + if (inthash_read((inthash)cache->hashtable,buff,(long int*)&pos)) { + if (fseek(cache->olddat,((pos>0)?pos:(-pos)),SEEK_SET) == 0) { + int len; + cache_rint(cache->olddat,&len); + if (len>0) { + char* mem_buff=(char*)malloct(len+4); /* Plus byte 0 */ + if (mem_buff) { + if ((int)fread(mem_buff,1,len,cache->olddat)==len) { // lire tout (y compris statuscode etc)*/ + *inbuff=mem_buff; + *inlen=len; + return 1; + } else + freet(mem_buff); + } + } + } + } + } +#endif + *inbuff=NULL; + *inlen=0; + return 0; +} + +// renvoyer uniquement en tête, ou NULL si erreur +htsblk* cache_header(httrackp* opt,cache_back* cache,char* adr,char* fil) { + htsblk* r; + NOSTATIC_RESERVE(r, htsblk, 1); + *r=cache_read(opt,cache,adr,fil,NULL); // test uniquement + if (r->statuscode != -1) + return r; + else + return NULL; +} + + +// Initialisation du cache: créer nouveau, renomer ancien, charger.. +void cache_init(cache_back* cache,httrackp* opt) { + // --- + // utilisation du cache: renommer ancien éventuel et charger index + if (opt->cache) { +#if DEBUGCA + printf("cache init: "); +#endif +#if HTS_WIN + mkdir(fconcat(opt->path_log,"hts-cache")); +#else + mkdir(fconcat(opt->path_log,"hts-cache"),HTS_PROTECT_FOLDER); +#endif + if ((fexist(fconcat(opt->path_log,"hts-cache/new.dat"))) && (fexist(fconcat(opt->path_log,"hts-cache/new.ndx")))) { // il existe déja un cache précédent.. renommer +#if DEBUGCA + printf("work with former cache\n"); +#endif + if (fexist(fconcat(opt->path_log,"hts-cache/old.dat"))) + remove(fconcat(opt->path_log,"hts-cache/old.dat")); + if (fexist(fconcat(opt->path_log,"hts-cache/old.ndx"))) + remove(fconcat(opt->path_log,"hts-cache/old.ndx")); + + rename(fconcat(opt->path_log,"hts-cache/new.dat"),fconcat(opt->path_log,"hts-cache/old.dat")); + rename(fconcat(opt->path_log,"hts-cache/new.ndx"),fconcat(opt->path_log,"hts-cache/old.ndx")); + } else { // un des deux (ou les deux) fichiers cache absents: effacer l'autre éventuel +#if DEBUGCA + printf("new cache\n"); +#endif + if (fexist(fconcat(opt->path_log,"hts-cache/new.dat"))) + remove(fconcat(opt->path_log,"hts-cache/new.dat")); + if (fexist(fconcat(opt->path_log,"hts-cache/new.ndx"))) + remove(fconcat(opt->path_log,"hts-cache/new.ndx")); + } + + // charger index cache précédent + if ((fexist(fconcat(opt->path_log,"hts-cache/old.dat"))) && (fexist(fconcat(opt->path_log,"hts-cache/old.ndx")))) { // cache précédent + if ((fsize(fconcat(opt->path_log,"hts-cache/old.dat"))>=0) && (fsize(fconcat(opt->path_log,"hts-cache/old.ndx"))>0)) { + FILE* oldndx=NULL; +#if DEBUGCA + printf("..load cache\n"); +#endif + cache->olddat=fopen(fconcat(opt->path_log,"hts-cache/old.dat"),"rb"); + oldndx=fopen(fconcat(opt->path_log,"hts-cache/old.ndx"),"rb"); + // les deux doivent être ouvrables + if ((cache->olddat==NULL) && (oldndx!=NULL)) { + fclose(oldndx); + oldndx=NULL; + } + if ((cache->olddat!=NULL) && (oldndx==NULL)) { + fclose(cache->olddat); + cache->olddat=NULL; + } + // lire index + if (oldndx!=NULL) { + int buffl; + fclose(oldndx); oldndx=NULL; + // lire ndx, et lastmodified + buffl=fsize(fconcat(opt->path_log,"hts-cache/old.ndx")); + cache->use=readfile(fconcat(opt->path_log,"hts-cache/old.ndx")); + if (cache->use!=NULL) { + char firstline[256]; + char* a=cache->use; + a+=cache_brstr(a,firstline); + if (strncmp(firstline,"CACHE-",6)==0) { // Nouvelle version du cache + if (strncmp(firstline,"CACHE-1.",8)==0) { // Version 1.1x + cache->version=(int)(firstline[8]-'0'); // cache 1.x + if (cache->version <= 2) { + a+=cache_brstr(a,firstline); + strcpy(cache->lastmodified,firstline); + } else { + if (opt->errlog) { + fspc(opt->errlog,"error"); fprintf(opt->errlog,"Cache: version 1.%d not supported, ignoring current cache"LF,cache->version); + fflush(opt->errlog); + } + fclose(cache->olddat); + cache->olddat=NULL; + freet(cache->use); + cache->use=NULL; + } + } else { // non supporté + if (opt->errlog) { + fspc(opt->errlog,"error"); fprintf(opt->errlog,"Cache: %s not supported, ignoring current cache"LF,firstline); + fflush(opt->errlog); + } + fclose(cache->olddat); + cache->olddat=NULL; + freet(cache->use); + cache->use=NULL; + } + /* */ + } else { // Vieille version du cache + /* */ + if (opt->log) { + fspc(opt->log,"warning"); fprintf(opt->log,"Cache: importing old cache format"LF); + fflush(opt->log); + } + cache->version=0; // cache 1.0 + strcpy(cache->lastmodified,firstline); + } + opt->is_update=1; // signaler comme update + + /* Create hash table for the cache (MUCH FASTER!) */ +#if HTS_FAST_CACHE + if (cache->use) { + char line[HTS_URLMAXSIZE*2]; + char linepos[256]; + int pos; + while ( (a!=NULL) && (a < (cache->use+buffl) ) ) { + a=strchr(a+1,'\n'); /* start of line */ + if (a) { + a++; + /* read "host/file" */ + a+=binput(a,line,HTS_URLMAXSIZE); + a+=binput(a,line+strlen(line),HTS_URLMAXSIZE); + /* read position */ + a+=binput(a,linepos,200); + sscanf(linepos,"%d",&pos); + inthash_add((inthash)cache->hashtable,line,pos); + } + } + /* Not needed anymore! */ + freet(cache->use); + cache->use=NULL; + } +#endif + } + } + } // taille cache>0 + } // cache precedent existe + +#if DEBUGCA + printf("..create cache\n"); +#endif + // ouvrir caches actuels + cache->dat=fopen(fconcat(opt->path_log,"hts-cache/new.dat"),"wb"); + cache->ndx=fopen(fconcat(opt->path_log,"hts-cache/new.ndx"),"wb"); + // les deux doivent être ouvrables + if ((cache->dat==NULL) && (cache->ndx!=NULL)) { + fclose(cache->ndx); + cache->ndx=NULL; + } + if ((cache->dat!=NULL) && (cache->ndx==NULL)) { + fclose(cache->dat); + cache->dat=NULL; + } + + if (cache->ndx!=NULL) { + char s[256]; + + cache_wstr(cache->dat,"CACHE-1.2"); + fflush(cache->dat); + cache_wstr(cache->ndx,"CACHE-1.2"); + fflush(cache->ndx); + // + time_gmt_rfc822(s); // date et heure actuelle GMT pour If-Modified-Since.. + cache_wstr(cache->ndx,s); + fflush(cache->ndx); // un petit fflush au cas où + + // supprimer old.lst + if (fexist(fconcat(opt->path_log,"hts-cache/old.lst"))) + remove(fconcat(opt->path_log,"hts-cache/old.lst")); + // renommer + if (fexist(fconcat(opt->path_log,"hts-cache/new.lst"))) + rename(fconcat(opt->path_log,"hts-cache/new.lst"),fconcat(opt->path_log,"hts-cache/old.lst")); + // ouvrir + cache->lst=fopen(fconcat(opt->path_log,"hts-cache/new.lst"),"wb"); + { + filecreate_params tmp; + strcpy(tmp.path,opt->path_html); // chemin + tmp.lst=cache->lst; // fichier lst + filenote("",&tmp); // initialiser filecreate + } + + // supprimer old.txt + if (fexist(fconcat(opt->path_log,"hts-cache/old.txt"))) + remove(fconcat(opt->path_log,"hts-cache/old.txt")); + // renommer + if (fexist(fconcat(opt->path_log,"hts-cache/new.txt"))) + rename(fconcat(opt->path_log,"hts-cache/new.txt"),fconcat(opt->path_log,"hts-cache/old.txt")); + // ouvrir + cache->txt=fopen(fconcat(opt->path_log,"hts-cache/new.txt"),"wb"); + if (cache->txt) { + fprintf(cache->txt,"date\tsize'/'remotesize\tflags(request:Update,Range state:File response:Modified,Chunked,gZipped)\t"); + fprintf(cache->txt,"statuscode\tstatus ('servermsg')\tMIME\tEtag|Date\tURL\tlocalfile\t(from URL)"LF); + } + + // test + // cache_writedata(cache->ndx,cache->dat,"//[TEST]//","test1","TEST PIPO",9); + } + + } + +} + + + + +// lire un fichier.. (compatible \0) +char* readfile(char* fil) { + char* adr=NULL; + int len=0; + len=fsize(fil); + if (len>0) { // existe + FILE* fp; + fp=fopen(fconv(fil),"rb"); + if (fp!=NULL) { // n'existe pas (!) + adr=(char*) malloct(len+1); + if (adr!=NULL) { + if ((int) fread(adr,1,len,fp)!=len) { // fichier endommagé ? + freet(adr); + adr=NULL; + } else + *(adr+len)='\0'; + } + fclose(fp); + } + } + return adr; +} + +char* readfile_or(char* fil,char* defaultdata) { + char* realfile=fil; + char* ret; + if (!fexist(fil)) + realfile=fconcat(hts_rootdir(NULL),fil); + ret=readfile(realfile); + if (ret) + return ret; + else { + char *adr=malloct(strlen(defaultdata)+2); + if (adr) { + strcpy(adr,defaultdata); + return adr; + } + } + return NULL; +} + +// écriture/lecture d'une chaîne sur un fichier +// -1 : erreur, sinon 0 +int cache_wstr(FILE* fp,char* s) { + int i; + char buff[256+4]; + i=strlen(s); + sprintf(buff,"%d\n",i); + if (fwrite(buff,1,strlen(buff),fp) != strlen(buff)) + return -1; + if (i>0) + if ((int) fwrite(s,1,i,fp) != i) + return -1; + return 0; +} +void cache_rstr(FILE* fp,char* s) { + int i; + char buff[256+4]; + linput(fp,buff,256); + sscanf(buff,"%d",&i); + if (i>0) + fread(s,1,i,fp); + *(s+i)='\0'; +} +int cache_brstr(char* adr,char* s) { + int i; + int off; + char buff[256+4]; + off=binput(adr,buff,256); + adr+=off; + sscanf(buff,"%d",&i); + if (i>0) + strncpy(s,adr,i); + *(s+i)='\0'; + off+=i; + return off; +} +int cache_quickbrstr(char* adr,char* s) { + int i; + int off; + char buff[256+4]; + off=binput(adr,buff,256); + adr+=off; + sscanf(buff,"%d",&i); + if (i>0) + strncpy(s,adr,i); + *(s+i)='\0'; + off+=i; + return off; +} +/* idem, mais en int */ +int cache_brint(char* adr,int* i) { + char s[256]; + int r=cache_brstr(adr,s); + if (r!=-1) + sscanf(s,"%d",i); + return r; +} +void cache_rint(FILE* fp,int* i) { + char s[256]; + cache_rstr(fp,s); + sscanf(s,"%d",i); +} +int cache_wint(FILE* fp,int i) { + char s[256]; + sprintf(s,"%d",(int) i); + return cache_wstr(fp,s); +} +void cache_rLLint(FILE* fp,LLint* i) { + char s[256]; + cache_rstr(fp,s); + sscanf(s,LLintP,i); +} +int cache_wLLint(FILE* fp,LLint i) { + char s[256]; + sprintf(s,LLintP,(LLint) i); + return cache_wstr(fp,s); +} +// -- cache -- |