summaryrefslogtreecommitdiff
path: root/src/htscache.c
diff options
context:
space:
mode:
authorXavier Roche <xroche@users.noreply.github.com>2012-03-19 12:36:11 +0000
committerXavier Roche <xroche@users.noreply.github.com>2012-03-19 12:36:11 +0000
commitad5b7acc19290ff91e0f42a0de448a26760fcf99 (patch)
tree2d1867758835fd0c4e443ff3cc7e5c774af85874 /src/htscache.c
Imported httrack 3.20.2
Diffstat (limited to 'src/htscache.c')
-rw-r--r--src/htscache.c881
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 --