home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 71 / CDROM71.ISO / internet / navoff / data1.cab / Sources / src / htscache.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-01  |  26.9 KB  |  839 lines

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