home *** CD-ROM | disk | FTP | other *** search
/ PC Open 48 / pcopen48.iso / Internet / HtTrack / DATA1.CAB / Sources / src / htscache.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-21  |  25.4 KB  |  804 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche, Yann Philippot
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. This project has been developed by Xavier Roche and Yann Philippot,
  29. from the company Serianet at Caen, France (http://www.serianet.com)
  30.  
  31. Please visit our Website: http://www.httrack.com
  32. */
  33.  
  34.  
  35. /* ------------------------------------------------------------ */
  36. /* File: httrack.c subroutines:                                 */
  37. /*       cache system (index and stores files in cache)         */
  38. /* Author: Xavier Roche                                         */
  39. /* ------------------------------------------------------------ */
  40.  
  41. #include "htscache.h"
  42.  
  43. /* specific definitions */
  44. #include "htsbase.h"
  45. #include "htsbasenet.h"
  46. #include "htsmd5.h"
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. /* END specific definitions */
  51.  
  52.  
  53. // routines de mise en cache
  54.  
  55. /*
  56.   VERSION 1.0 :
  57.   -----------
  58.  
  59. .ndx file
  60.  file with data
  61.    <string>(date/time) [ <string>(hostname+filename) (datfile_position_ascii) ] * number_of_links
  62.  file without data
  63.    <string>(date/time) [ <string>(hostname+filename) (-datfile_position_ascii) ] * number_of_links
  64.  
  65. .dat file
  66.  [ file ] * 
  67. with
  68.   file= (with data)
  69.    [ bytes ] * sizeof(htsblk header) [ bytes ] * n(length of file given in htsblk header)
  70.  file= (without data)
  71.    [ bytes ] * sizeof(htsblk header)
  72. with
  73.  <string>(name) = <length in ascii>+<lf>+<data>
  74.  
  75.  
  76.   VERSION 1.1 :
  77.   -----------
  78.  
  79. .ndx file
  80.  file with data
  81.    <string>("CACHE-1.1") <string>(date/time) [ <string>(hostname+filename) (datfile_position_ascii) ] * number_of_links
  82.  file without data
  83.    <string>("CACHE-1.1") <string>(date/time) [ <string>(hostname+filename) (-datfile_position_ascii) ] * number_of_links
  84.  
  85. .dat file
  86.    <string>("CACHE-1.1") [ [Header_1.1] [bytes] * n(length of file given in header) ] *
  87. with
  88.  Header_1.1=
  89.    <int>(statuscode)
  90.    <int>(size)
  91.    <string>(msg)
  92.    <string>(contenttype)
  93.    <string>(last-modified)
  94.    <string>(Etag)
  95.    [<string>"SD" <string>(supplemental data)]
  96.    [<string>"SD" <string>(supplemental data)]
  97.    ...
  98.    <string>"HTS" (end of header)
  99.    <int>(number of bytes of data) (0 if no data written)
  100. */
  101.  
  102. // Nouveau: si != text/html ne stocke que la taille
  103.  
  104. /* Ajout d'un fichier en cache */
  105. void cache_add(htsblk r,char* url_adr,char* url_fil,char* url_save,FILE* cache_ndx,FILE* cache_dat,int all_in_cache) {
  106.   int pos;
  107.   char s[256];
  108.   char buff[HTS_URLMAXSIZE*4];
  109.   int ok=1;
  110.   int dataincache=0;    // donnΘe en cache?
  111.   /*char digest[32+2];*/
  112.   /*digest[0]='\0';*/
  113.  
  114.   // Longueur url_save==0?
  115.   if ( (strnotempty(url_save)==0) ) {
  116.     if (strcmp(url_fil,"/robots.txt")==0)        // robots.txt
  117.       dataincache=1;
  118.     else
  119.       return;   // erreur (sauf robots.txt)
  120.   }
  121.  
  122.   if (r.size <= 0)   // taille <= 0 
  123.     return;          // refusΘ..
  124.  
  125.   // Mettre les *donΘes* en cache ?
  126.   if (is_hypertext_mime(r.contenttype))    // html, mise en cache des donnΘes et 
  127.     dataincache=1;                               // pas uniquement de l'en tΩte
  128.   else if (all_in_cache)
  129.     dataincache=1;                               // forcer tout en cache
  130.  
  131.   /* calcul md5 ? */
  132.   /*
  133.   if (is_hypertext_mime(r.contenttype)) {    // html, calcul MD5
  134.     if (r.adr) {
  135.       domd5mem(r.adr,r.size,digest,1,0);
  136.     }
  137.   }*/
  138.  
  139.   // Position
  140.   fflush(cache_dat); fflush(cache_ndx);
  141.   pos=ftell(cache_dat);
  142.   // Θcrire pointeur seek, adresse, fichier
  143.   if (dataincache)   // patcher
  144.     sprintf(s,"%d\n",pos);    // ecrire tel que (eh oui Θvite les \0..)
  145.   else
  146.     sprintf(s,"%d\n",-pos);   // ecrire tel que (eh oui Θvite les \0..)
  147.  
  148.   // data
  149.   // Θcrire donnΘes en-tΩte, donnΘes fichier
  150.   /*if (!dataincache) {   // patcher
  151.     r.size=-r.size;  // nΘgatif
  152.   }*/
  153.  
  154.   // Construction header
  155.   ok=0;
  156.   if (cache_wint(cache_dat,r.statuscode)!=-1)       // statuscode
  157.   if (cache_wLLint(cache_dat,r.size)!=-1)           // size
  158.   if (cache_wstr(cache_dat,r.msg)!=-1)              // msg
  159.   if (cache_wstr(cache_dat,r.contenttype)!=-1)      // contenttype
  160.   if (cache_wstr(cache_dat,r.lastmodified)!=-1)     // last-modified
  161.   if (cache_wstr(cache_dat,r.etag)!=-1)             // Etag
  162.   if (cache_wstr(cache_dat,(r.location!=NULL)?r.location:"")!=-1)         // 'location' pour moved
  163.   /*if (cache_wstr(cache_dat,"SD")!=-1)               // more data
  164.   if (cache_wstr(cache_dat,digest)!=-1)             // MD5 (version 
  165.   */
  166.   if (cache_wstr(cache_dat,"HTS")!=-1)              // end of header
  167.     ok=1;       /* ok */
  168.   // Fin construction header
  169.  
  170.   /*if ((int) fwrite((char*) &r,1,sizeof(htsblk),cache_dat) == sizeof(htsblk)) {*/
  171.   if (ok) {
  172.     if (dataincache) {    // mise en cache?
  173.       if (!r.adr) {       /* taille nulle (parfois en cas de 301 */
  174.         if (cache_wLLint(cache_dat,0)==-1)          /* 0 bytes */
  175.           ok=0;
  176.       } else if (r.is_write==0) {  // en mΘmoire, recopie directe
  177.         if (cache_wLLint(cache_dat,r.size)!=-1) {
  178.           if (r.size>0) {   // taille>0
  179.             if ((INTsys) fwrite(r.adr,1,(INTsys)r.size,cache_dat)!=r.size)
  180.               ok=0;
  181.           } else    // taille=0, ne rien Θcrire
  182.             ok=0;
  183.         } else
  184.           ok=0;
  185.       } else {  // recopier fichier dans cache
  186.         FILE* fp;
  187.         // On recopie le fichier..
  188.         LLint file_size=fsize(fconv(url_save));
  189.         if (file_size>=0) {
  190.           if (cache_wLLint(cache_dat,file_size)!=-1) {
  191.             fp=fopen(fconv(url_save),"rb");
  192.             if (fp!=NULL) {
  193.               char buff[32768];
  194.               int nl;
  195.               do {
  196.                 nl=fread(buff,1,32768,fp);
  197.                 if (nl>0) { 
  198.                   if ((INTsys) fwrite(buff,1,(INTsys)nl,cache_dat)!=nl) {  // erreur
  199.                     nl=-1;
  200.                     ok=0;
  201.                   }
  202.                 }
  203.               } while(nl>0);
  204.               fclose(fp);
  205.             } else ok=0;
  206.           } else ok=0;
  207.         } else ok=0;
  208.       }
  209.     } else {
  210.       if (cache_wLLint(cache_dat,0)==-1)          /* 0 bytes */
  211.         ok=0;
  212.     }
  213.   } else ok=0;
  214.   /*if (!dataincache) {   // dΘpatcher
  215.     r.size=-r.size;
  216.   }*/
  217.  
  218.   // index
  219.   // adresse+cr+fichier+cr
  220.   if (ok) {
  221.     buff[0]='\0'; strcat(buff,url_adr); strcat(buff,"\n"); strcat(buff,url_fil); strcat(buff,"\n");
  222.     cache_wstr(cache_ndx,buff);
  223.     fwrite(s,1,strlen(s),cache_ndx);
  224.   }  // si ok=0 on a peut Ωtre Θcrit des donnΘes pour rien mais on s'en tape
  225.   
  226.   // en cas de plantage, on aura au moins le cache!
  227.   fflush(cache_dat); fflush(cache_ndx);
  228. }
  229.  
  230.  
  231. // lecture d'un fichier dans le cache
  232. // si save==null alors test unqiquement
  233. htsblk cache_read(httrackp* opt,cache_back* cache,char* adr,char* fil,char* save) {
  234. #if HTS_FAST_CACHE
  235.   long int hash_pos;
  236.   int hash_pos_return;
  237. #else
  238.   char* a;
  239. #endif
  240.   char buff[HTS_URLMAXSIZE*2];
  241.   static char location[HTS_URLMAXSIZE*2];
  242.   htsblk r;
  243.   int ok=0;
  244.   int header_only=0;
  245.  
  246.   bzero((char *)&r, sizeof(htsblk)); r.soc=INVALID_SOCKET; strcpy(location,""); r.location=location;
  247. #if HTS_FAST_CACHE
  248.   strcpy(buff,adr); strcat(buff,fil);
  249.   hash_pos_return=inthash_read((hash_chain**)cache->hash,cache->hash_size,buff,(long int*)&hash_pos);
  250. #else
  251.   buff[0]='\0'; strcat(buff,"\n"); strcat(buff,adr); strcat(buff,"\n"); strcat(buff,fil); strcat(buff,"\n");
  252.   if (cache->use)
  253.     a=strstr(cache->use,buff);
  254.   else
  255.     a=NULL;       // forcer erreur
  256. #endif
  257.  
  258.   // en cas de succΦs
  259. #if HTS_FAST_CACHE
  260.   if (hash_pos_return) {
  261. #else
  262.   if (a!=NULL) {  // OK existe en cache!
  263. #endif
  264.     int pos;
  265. #if DEBUGCA
  266.     fprintf(stdout,"..cache: %s%s at ",adr,fil);
  267. #endif
  268.     
  269. #if HTS_FAST_CACHE
  270.     pos=hash_pos;     /* simply */
  271. #else
  272.     a+=strlen(buff);
  273.     sscanf(a,"%d",&pos);    // lire position
  274. #endif
  275. #if DEBUGCA
  276.     printf("%d\n",pos);
  277. #endif
  278.  
  279.     fflush(cache->olddat); 
  280.     if (fseek(cache->olddat,((pos>0)?pos:(-pos)),SEEK_SET) == 0) {
  281.       /* Importer cache1.0 */
  282.       if (cache->version==0) {
  283.         OLD_htsblk old_r;
  284.         if (fread((char*) &old_r,1,sizeof(old_r),cache->olddat)==sizeof(old_r)) { // lire tout (y compris statuscode etc)
  285.           r.statuscode=old_r.statuscode;
  286.           r.size=old_r.size;        // taille fichier
  287.           strcpy(r.msg,old_r.msg);
  288.           strcpy(r.contenttype,old_r.contenttype);
  289.           ok=1;     /* import  ok */
  290.         }
  291.       /* */
  292.       /* Cache 1.1 */
  293.       } else {
  294.         char check[256];
  295.         LLint size_read;
  296.         check[0]='\0';
  297.         //
  298.         cache_rint(cache->olddat,&r.statuscode);
  299.         cache_rLLint(cache->olddat,&r.size);
  300.         cache_rstr(cache->olddat,r.msg);
  301.         cache_rstr(cache->olddat,r.contenttype);
  302.         cache_rstr(cache->olddat,r.lastmodified);
  303.         cache_rstr(cache->olddat,r.etag);
  304.         cache_rstr(cache->olddat,r.location);
  305.         cache_rstr(cache->olddat,check);
  306.         /*if (strcmp(check,"SD")==0) {        // version 1.110: md5
  307.           cache_rstr(cache->olddat,r.digest);
  308.           cache_rstr(cache->olddat,check);
  309.         }*/
  310.         if (strcmp(check,"HTS")==0) {           /* intΘgritΘ OK */
  311.           ok=1;
  312.         }
  313.         cache_rLLint(cache->olddat,&size_read);       /* lire size pour Ωtre s√r de la taille dΘclarΘe (rΘΘcrire) */
  314.         if (size_read>0) {                         /* si inscrite ici */
  315.           r.size=size_read;
  316.         } else {                              /* pas de donnΘes directement dans le cache, fichier prΘsent? */
  317.           if (r.statuscode!=200)
  318.             header_only=1;          /* que l'en tΩte ici! */
  319.         }
  320.       }
  321.  
  322.       /* Remplir certains champs */
  323.       r.totalsize=r.size;
  324.  
  325.       // lecture du header (y compris le statuscode)
  326.       /*if (fread((char*) &r,1,sizeof(htsblk),cache->olddat)==sizeof(htsblk)) { // lire tout (y compris statuscode etc)*/
  327.       if (ok) {
  328.         // sΘcuritΘ
  329.         r.adr=NULL;
  330.         r.out=NULL;
  331.         ////r.location=NULL;  non, fixΘe lors des 301 ou 302
  332.         r.fp=NULL;
  333.         
  334.         if ( (r.statuscode>=0) && (r.statuscode<=999)
  335.           && (r.notmodified>=0)  && (r.notmodified<=9) ) {   // petite vΘrif intΘgritΘ
  336.           if ((save) && (!header_only) ) {     /* ne pas lire uniquement header */
  337.             //int to_file=0;
  338.             
  339.             r.adr=NULL; r.soc=INVALID_SOCKET; 
  340.             // // r.location=NULL;
  341.             
  342. #if HTS_DIRECTDISK
  343.             // Court-circuit:
  344.             // Peut-on stocker le fichier directement sur disque?
  345.             if ((r.statuscode==200) && (!is_hypertext_mime(r.contenttype)) && (strnotempty(save))) {    // pas HTML, Θcrire sur disk directement
  346.               int ok=0;
  347.               
  348.               r.is_write=1;    // Θcrire
  349.               if (fexist(antislash(save))) {  // un fichier existe dΘja
  350.                 //if (fsize(antislash(save))==r.size) {  // mΩme taille -- NON tant pis (taille mal declaree)
  351.                 ok=1;    // plus rien α faire
  352.                 filenote(save,NULL);        // noter comme connu
  353.                 //}
  354.               }
  355.               
  356.               if ((pos<0) && (!ok)) { // Pas de donnΘe en cache et fichier introuvable : erreur!
  357.                 if (opt->norecatch) {
  358.                   FILE* fp;
  359.                   fp=filecreate(save);
  360.                   if (fp) fclose(fp);
  361.                   //
  362.                   r.statuscode=-1;
  363.                   strcpy(r.msg,"File deleted by user not recaught");
  364.                   ok=1;     // ne pas rΘcupΘrer (et pas d'erreur)
  365.                 } else {
  366.                   r.statuscode=-1;
  367.                   strcpy(r.msg,"Previous cache file not found");
  368.                   ok=1;    // ne pas rΘcupΘrer
  369.                 }
  370.               }
  371.               
  372.               if (!ok) {  
  373.                 r.out=filecreate(save);
  374. #if HDEBUG
  375.                 printf("direct-disk: %s\n",save);
  376. #endif
  377.                 if (r.out!=NULL) {
  378.                   char buff[32768+4];
  379.                   LLint nl;
  380.                   LLint size;
  381.                   size=r.size;
  382.                   do {
  383.                     nl=fread(buff,1,(INTsys) minimum(size,32768),cache->olddat);
  384.                     if (nl>0) {
  385.                       size-=nl; 
  386.                       if ((INTsys) fwrite(buff,1,(INTsys)nl,r.out)!=nl) {  // erreur
  387.                         r.statuscode=-1;
  388.                         strcpy(r.msg,"Cache Read Error : Read To Disk");
  389.                       }
  390.                     }
  391.                   } while((nl>0) && (size>0) && (r.statuscode!=-1));
  392.                   
  393.                   fclose(r.out);
  394.                   r.out=NULL;
  395. #if HTS_WIN==0
  396.                   chmod(save,HTS_ACCESS_FILE);      
  397. #endif          
  398.                   usercommand(0,NULL,antislash(save));
  399.                 } else {
  400.                   r.statuscode=-1;
  401.                   strcpy(r.msg,"Cache Write Error : Unable to Create File");
  402.                   //printf("%s\n",save);
  403.                 }
  404.               }
  405.               
  406.             } else
  407. #endif
  408.             { // lire en mΘmoire
  409.               
  410.               if (pos<0) { // Pas de donnΘe en cache, bizzard car html!!!
  411.                 r.statuscode=-1;
  412.                 strcpy(r.msg,"Previous cache file not found (2)");
  413.               } else {
  414.                 // lire fichier (d'un coup)
  415.                 r.adr=(char*) malloct((INTsys)r.size+4);
  416.                 if (r.adr!=NULL) {
  417.                   if ((INTsys) fread(r.adr,1,(INTsys)r.size,cache->olddat)!=r.size) {  // erreur
  418.                     freet(r.adr);
  419.                     r.adr=NULL;
  420.                     r.statuscode=-1;
  421.                     strcpy(r.msg,"Cache Read Error : Read Data");
  422.                   }
  423.                   //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode);
  424.                 } else {  // erreur
  425.                   r.statuscode=-1;
  426.                   strcpy(r.msg,"Cache Memory Error");
  427.                 }
  428.               }
  429.             }
  430.           }    // si save==null, ne rien charger (juste en tΩte)
  431.         } else {
  432. #if DEBUGCA
  433.           printf("Cache Read Error : Bad Data");
  434. #endif
  435.           r.statuscode=-1;
  436.           strcpy(r.msg,"Cache Read Error : Bad Data");
  437.         }
  438.       } else {  // erreur
  439. #if DEBUGCA
  440.         printf("Cache Read Error : Read Header");
  441. #endif
  442.         r.statuscode=-1;
  443.         strcpy(r.msg,"Cache Read Error : Read Header");
  444.       }
  445.     } else {
  446. #if DEBUGCA
  447.       printf("Cache Read Error : Seek Failed");
  448. #endif
  449.       r.statuscode=-1;
  450.       strcpy(r.msg,"Cache Read Error : Seek Failed");
  451.     }
  452.   } else {
  453. #if DEBUGCA
  454.     printf("File Cache Not Found");
  455. #endif
  456.     r.statuscode=-1;
  457.     strcpy(r.msg,"File Cache Not Found");
  458.   }
  459.   return r;
  460. }
  461.  
  462. /* write (string1-string2)-data in cache */
  463. /* 0 if failed */
  464. int cache_writedata(FILE* cache_ndx,FILE* cache_dat,char* str1,char* str2,char* outbuff,int len) {
  465.   if (cache_dat) {
  466.     char buff[HTS_URLMAXSIZE*4];
  467.     char s[256];
  468.     int pos;
  469.     fflush(cache_dat); fflush(cache_ndx);
  470.     pos=ftell(cache_dat);
  471.     /* first write data */
  472.     if (cache_wint(cache_dat,len)!=-1) {       // length
  473.       if ((INTsys) fwrite(outbuff,1,(INTsys)len,cache_dat) == (INTsys) len) {   // data
  474.         /* then write index */
  475.         sprintf(s,"%d\n",pos);
  476.         buff[0]='\0'; strcat(buff,str1); strcat(buff,"\n"); strcat(buff,str2); strcat(buff,"\n");
  477.         cache_wstr(cache_ndx,buff);
  478.         if (fwrite(s,1,strlen(s),cache_ndx) == strlen(s)) {
  479.           fflush(cache_dat); fflush(cache_ndx);
  480.           return 1;
  481.         }
  482.       }
  483.     }
  484.   }
  485.   return 0;
  486. }
  487.  
  488. /* read the data corresponding to (string1-string2) in cache */
  489. /* 0 if failed */
  490. int cache_readdata(cache_back* cache,char* str1,char* str2,char** inbuff,int* inlen) {
  491. #if HTS_FAST_CACHE
  492.   if (cache->hash) {
  493.     char buff[HTS_URLMAXSIZE*4];
  494.     long int pos;
  495.     strcpy(buff,str1); strcat(buff,str2);
  496.     if (inthash_read((hash_chain**)cache->hash,cache->hash_size,buff,(long int*)&pos)) {
  497.       if (fseek(cache->olddat,((pos>0)?pos:(-pos)),SEEK_SET) == 0) {
  498.         int len;
  499.         cache_rint(cache->olddat,&len);
  500.         if (len>0) {
  501.           char* mem_buff=(char*)malloc(len+4);    /* Plus byte 0 */
  502.           if (mem_buff) {
  503.             if ((int)fread(mem_buff,1,len,cache->olddat)==len) { // lire tout (y compris statuscode etc)*/
  504.               *inbuff=mem_buff;
  505.               *inlen=len;
  506.               return 1;
  507.             } else
  508.               free(mem_buff);
  509.           }
  510.         }
  511.       }
  512.     }
  513.   }
  514. #endif
  515.   *inbuff=NULL;
  516.   *inlen=0;
  517.   return 0;
  518. }
  519.  
  520. // renvoyer uniquement en tΩte, ou NULL si erreur
  521. htsblk* cache_header(httrackp* opt,cache_back* cache,char* adr,char* fil) {
  522.   static htsblk r;
  523.   r=cache_read(opt,cache,adr,fil,NULL);              // test uniquement
  524.   if (r.statuscode != -1)
  525.     return &r;
  526.   else
  527.     return NULL;
  528. }
  529.  
  530.           
  531. // Initialisation du cache: crΘer nouveau, renomer ancien, charger..
  532. void cache_init(cache_back* cache,httrackp* opt) {
  533.   // ---
  534.   // utilisation du cache: renommer ancien Θventuel et charger index
  535.   if (opt->cache) {
  536. #if DEBUGCA
  537.     printf("cache init: ");
  538. #endif
  539. #if HTS_WIN
  540.     mkdir(fconcat(opt->path_log,"hts-cache"));
  541. #else
  542.     mkdir(fconcat(opt->path_log,"hts-cache"),HTS_PROTECT_FOLDER);
  543. #endif
  544.     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
  545. #if DEBUGCA
  546.       printf("work with former cache\n");
  547. #endif
  548.       if (fexist(fconcat(opt->path_log,"hts-cache/old.dat")))
  549.         remove(fconcat(opt->path_log,"hts-cache/old.dat"));
  550.       if (fexist(fconcat(opt->path_log,"hts-cache/old.ndx")))
  551.         remove(fconcat(opt->path_log,"hts-cache/old.ndx"));
  552.       
  553.       rename(fconcat(opt->path_log,"hts-cache/new.dat"),fconcat(opt->path_log,"hts-cache/old.dat"));
  554.       rename(fconcat(opt->path_log,"hts-cache/new.ndx"),fconcat(opt->path_log,"hts-cache/old.ndx"));
  555.     } else {  // un des deux (ou les deux) fichiers cache absents: effacer l'autre Θventuel
  556. #if DEBUGCA
  557.       printf("new cache\n");
  558. #endif
  559.       if (fexist(fconcat(opt->path_log,"hts-cache/new.dat")))
  560.         remove(fconcat(opt->path_log,"hts-cache/new.dat"));
  561.       if (fexist(fconcat(opt->path_log,"hts-cache/new.ndx")))
  562.         remove(fconcat(opt->path_log,"hts-cache/new.ndx"));
  563.     }
  564.     
  565.     // charger index cache prΘcΘdent
  566.     if ((fexist(fconcat(opt->path_log,"hts-cache/old.dat"))) && (fexist(fconcat(opt->path_log,"hts-cache/old.ndx")))) {  // cache prΘcΘdent
  567.       if ((fsize(fconcat(opt->path_log,"hts-cache/old.dat"))>=0) && (fsize(fconcat(opt->path_log,"hts-cache/old.ndx"))>0)) {
  568.         FILE* oldndx=NULL;
  569. #if DEBUGCA
  570.         printf("..load cache\n");
  571. #endif
  572.         cache->olddat=fopen(fconcat(opt->path_log,"hts-cache/old.dat"),"rb");        
  573.         oldndx=fopen(fconcat(opt->path_log,"hts-cache/old.ndx"),"rb");        
  574.         // les deux doivent Ωtre ouvrables
  575.         if ((cache->olddat==NULL) && (oldndx!=NULL)) {
  576.           fclose(oldndx);
  577.           oldndx=NULL;
  578.         }
  579.         if ((cache->olddat!=NULL) && (oldndx==NULL)) {
  580.           fclose(cache->olddat);
  581.           cache->olddat=NULL;
  582.         }
  583.         // lire index
  584.         if (oldndx!=NULL) {
  585.           int buffl;
  586.           fclose(oldndx); oldndx=NULL;
  587.           // lire ndx, et lastmodified
  588.           buffl=fsize(fconcat(opt->path_log,"hts-cache/old.ndx"));
  589.           cache->use=lirefichier(fconcat(opt->path_log,"hts-cache/old.ndx"));
  590.           if (cache->use!=NULL) {
  591.             char firstline[256];
  592.             char* a=cache->use;
  593.             a+=cache_brstr(a,firstline);
  594.             if (strncmp(firstline,"CACHE-",6)==0) {       // Nouvelle version du cache
  595.               if (strncmp(firstline,"CACHE-1.1",9)==0) {     // Version 1.1x
  596.                 cache->version=1;      // cache 1.1
  597.                 a+=cache_brstr(a,firstline);
  598.                 strcpy(cache->lastmodified,firstline); 
  599.               } else {        // non supportΘ
  600.                 if (opt->errlog) {
  601.                   fspc(opt->errlog,"error"); fprintf(opt->errlog,"Cache: %s not supported, ignoring current cache"LF,firstline);
  602.                   fflush(opt->errlog);
  603.                 }
  604.                 fclose(cache->olddat);
  605.                 cache->olddat=NULL;
  606.                 freet(cache->use);
  607.                 cache->use=NULL;
  608.               }
  609.               /* */
  610.             } else {              // Vieille version du cache
  611.               /* */
  612.               if (opt->log) {
  613.                 fspc(opt->log,"warning"); fprintf(opt->log,"Cache: importing old cache format"LF);
  614.                 fflush(opt->log);
  615.               }
  616.               cache->version=0;        // cache 1.0
  617.               strcpy(cache->lastmodified,firstline); 
  618.             }
  619.             opt->is_update=1;        // signaler comme update
  620.  
  621.             /* Create hash table for the cache (MUCH FASTER!) */
  622. #if HTS_FAST_CACHE
  623.             if (cache->use) {
  624.               char line[HTS_URLMAXSIZE*2];
  625.               char linepos[256];
  626.               int  pos;
  627.               while ( (a!=NULL) && (((int) a) < ((int)(cache->use+buffl))) ) {
  628.                 a=strchr(a+1,'\n');     /* start of line */
  629.                 if (a) {
  630.                   a++;
  631.                   /* read "host/file" */
  632.                   a+=binput(a,line,HTS_URLMAXSIZE);
  633.                   a+=binput(a,line+strlen(line),HTS_URLMAXSIZE);
  634.                   /* read position */
  635.                   a+=binput(a,linepos,200);
  636.                   sscanf(linepos,"%d",&pos);
  637.                   inthash_add((hash_chain**)cache->hash,cache->hash_size,line,pos);
  638.                 }
  639.               }
  640.               /* Not needed anymore! */
  641.               freet(cache->use);
  642.               cache->use=NULL;
  643.             }
  644. #endif
  645.           }
  646.         }
  647.       }  // taille cache>0
  648.     }  // cache precedent existe
  649.     
  650. #if DEBUGCA
  651.     printf("..create cache\n");
  652. #endif
  653.     // ouvrir caches actuels
  654.     cache->dat=fopen(fconcat(opt->path_log,"hts-cache/new.dat"),"wb");        
  655.     cache->ndx=fopen(fconcat(opt->path_log,"hts-cache/new.ndx"),"wb");        
  656.     // les deux doivent Ωtre ouvrables
  657.     if ((cache->dat==NULL) && (cache->ndx!=NULL)) {
  658.       fclose(cache->ndx);
  659.       cache->ndx=NULL;
  660.     }
  661.     if ((cache->dat!=NULL) && (cache->ndx==NULL)) {
  662.       fclose(cache->dat);
  663.       cache->dat=NULL;
  664.     }
  665.     
  666.     if (cache->ndx!=NULL) {
  667.       char s[256];
  668.       
  669.       cache_wstr(cache->dat,"CACHE-1.110");
  670.       fflush(cache->dat);
  671.       cache_wstr(cache->ndx,"CACHE-1.110");
  672.       fflush(cache->ndx);
  673.       //
  674.       time_gmt_rfc822(s);   // date et heure actuelle GMT pour If-Modified-Since..
  675.       cache_wstr(cache->ndx,s);        
  676.       fflush(cache->ndx);    // un petit fflush au cas o∙
  677.       
  678.       // supprimer old.lst
  679.       if (fexist(fconcat(opt->path_log,"hts-cache/old.lst")))
  680.         remove(fconcat(opt->path_log,"hts-cache/old.lst"));
  681.       // renommer
  682.       if (fexist(fconcat(opt->path_log,"hts-cache/new.lst")))
  683.         rename(fconcat(opt->path_log,"hts-cache/new.lst"),fconcat(opt->path_log,"hts-cache/old.lst"));
  684.       // ouvrir
  685.       cache->lst=fopen(fconcat(opt->path_log,"hts-cache/new.lst"),"wb");
  686.       {
  687.         filecreate_params tmp;
  688.         strcpy(tmp.path,opt->path_html);    // chemin
  689.         tmp.lst=cache->lst;                 // fichier lst
  690.         filenote("",&tmp);        // initialiser filecreate
  691.       }
  692.  
  693.       // test
  694.       // cache_writedata(cache->ndx,cache->dat,"//[TEST]//","test1","TEST PIPO",9);
  695.     }
  696.     
  697.   }
  698.   
  699. }
  700.   
  701.   
  702.   
  703.  
  704. // lire un fichier..
  705. char* lirefichier(char* fil) {
  706.   char* adr=NULL;
  707.   int len=0;
  708.   len=fsize(fil);
  709.   if (len>0) {  // existe
  710.     FILE* fp;
  711.     fp=fopen(fconv(fil),"rb");
  712.     if (fp!=NULL) {  // n'existe pas (!)
  713.       adr=(char*) malloct(len);
  714.       if (adr!=NULL) {
  715.         if ((int) fread(adr,1,len,fp)!=len) {    // fichier endommagΘ ?
  716.           freet(adr);
  717.           adr=NULL;
  718.         }
  719.       }
  720.       fclose(fp);
  721.     }
  722.   }
  723.   return adr;
  724. }
  725.  
  726. // Θcriture/lecture d'une chaεne sur un fichier
  727. // -1 : erreur, sinon 0
  728. int cache_wstr(FILE* fp,char* s) {
  729.   int i;
  730.   char buff[256];
  731.   i=strlen(s);
  732.   sprintf(buff,"%d\n",i);
  733.   if (fwrite(buff,1,strlen(buff),fp) != strlen(buff))
  734.     return -1;
  735.   if (i>0)
  736.   if ((int) fwrite(s,1,i,fp) != i)
  737.     return -1;
  738.   return 0;
  739. }
  740. void cache_rstr(FILE* fp,char* s) {
  741.   int i;
  742.   char buff[256];
  743.   linput(fp,buff,256);
  744.   sscanf(buff,"%d",&i);
  745.   if (i>0)
  746.     fread(s,1,i,fp);
  747.   *(s+i)='\0';
  748. }
  749. int cache_brstr(char* adr,char* s) {
  750.   int i;
  751.   int off;
  752.   char buff[256];
  753.   off=binput(adr,buff,256);
  754.   adr+=off;
  755.   sscanf(buff,"%d",&i);
  756.   if (i>0)
  757.     strncpy(s,adr,i);
  758.   *(s+i)='\0';
  759.   off+=i;
  760.   return off;
  761. }
  762. int cache_quickbrstr(char* adr,char* s) {
  763.   int i;
  764.   int off;
  765.   char buff[256];
  766.   off=binput(adr,buff,256);
  767.   adr+=off;
  768.   sscanf(buff,"%d",&i);
  769.   if (i>0)
  770.     strncpy(s,adr,i);
  771.   *(s+i)='\0';
  772.   off+=i;
  773.   return off;
  774. }
  775. /* idem, mais en int */
  776. int cache_brint(char* adr,int* i) {
  777.   char s[256];
  778.   int r=cache_brstr(adr,s);
  779.   if (r!=-1)
  780.     sscanf(s,"%d",i);
  781.   return r;
  782. }
  783. void cache_rint(FILE* fp,int* i) {
  784.   char s[256];
  785.   cache_rstr(fp,s);
  786.   sscanf(s,"%d",i);
  787. }
  788. int cache_wint(FILE* fp,int i) {
  789.   char s[256];
  790.   sprintf(s,"%d",(int) i);
  791.   return cache_wstr(fp,s);
  792. }
  793. void cache_rLLint(FILE* fp,LLint* i) {
  794.   char s[256];
  795.   cache_rstr(fp,s);
  796.   sscanf(s,LLintP,i);
  797. }
  798. int cache_wLLint(FILE* fp,LLint i) {
  799.   char s[256];
  800.   sprintf(s,LLintP,(LLint) i);
  801.   return cache_wstr(fp,s);
  802. }
  803. // -- cache --
  804.