home *** CD-ROM | disk | FTP | other *** search
/ Revista do CD-ROM 71 / CDROM71.ISO / internet / navoff / data1.cab / Sources / src / htsback.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-04-01  |  73.7 KB  |  1,942 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. /*       backing system (multiple socket download)              */
  39. /* Author: Xavier Roche                                         */
  40. /* ------------------------------------------------------------ */
  41.  
  42. #include "htsback.h"
  43.  
  44. /* specific definitions */
  45. #include "htsbase.h"
  46. #include "htsnet.h"
  47. #include "htsthread.h"
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. /* END specific definitions */
  52.  
  53. //#if HTS_WIN
  54. #include "htsftp.h"
  55. //#endif
  56.  
  57. #if HTS_WIN
  58. #ifndef __cplusplus
  59. // DOS
  60. #include <process.h>    /* _beginthread, _endthread */
  61. #endif
  62. #else
  63. #endif
  64.  
  65. #undef test_flush
  66. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  67.  
  68. // ---
  69. // routines de backing
  70. // retourne l'index d'un lien dans un tableau de backing
  71. int back_index(lien_back* back,int back_max,char* adr,char* fil,char* sav) {
  72.   register int i=0;
  73.   register int index=-1;
  74.   while( i<back_max ) {
  75.     if (back[i].status>=0)    // rΘception OU prΩt
  76.       if (strfield2(back[i].url_adr,adr)) {
  77.         if (strcmp(back[i].url_fil,fil)==0) {
  78.           if (index==-1)    /* first time we meet, store it */
  79.             index=i;
  80.           else if (strcmp(back[i].url_sav,sav)==0) {  /* oops, check sav too */
  81.             index=i;
  82.             return index;
  83.           }
  84.         }
  85.       }
  86.     i++;
  87.   }
  88.   return index;
  89. }
  90.  
  91. // nombre d'entrΘes libres dans le backing
  92. int back_available(lien_back* back,int back_max) {
  93.   int i;
  94.   int nb=0;
  95.   for(i=0;i<back_max;i++)
  96.     if (back[i].status==-1)     /* libre */
  97.       nb++;
  98.   return nb;
  99. }
  100.  
  101. // retourne estimation de la taille des html et fichiers stockΘs en mΘmoire
  102. LLint back_incache(lien_back* back,int back_max) {
  103.   int i;
  104.   LLint sum=0;
  105.   for(i=0;i<back_max;i++)
  106.     if (back[i].status!=-1)
  107.       if (back[i].r.adr)       // ne comptabilier que les blocs en mΘmoire
  108.         sum+=max(back[i].r.size,back[i].r.totalsize);
  109.   return sum;
  110. }
  111.  
  112. // le lien a-t-il ΘtΘ mis en backing?
  113. HTS_INLINE int back_exist(lien_back* back,int back_max,char* adr,char* fil,char* sav) {
  114.   return (back_index(back,back_max,adr,fil,sav)>=0);
  115. }
  116.  
  117. // nombre de sockets en tΓche de fond
  118. int back_nsoc(lien_back* back,int back_max) {
  119.   int n=0;
  120.   int i;
  121.   for(i=0;i<back_max;i++)
  122.     if (back[i].status>0)    // rΘception uniquement
  123.       n++;
  124.  
  125.   return n;
  126. }
  127.  
  128. // effacer entrΘe
  129. int back_delete(lien_back* back,int p) {
  130.   if (p>=0) {    // on sait jamais..
  131.     // VΘrificateur d'intΘgritΘ
  132.     #if DEBUG_CHECKINT
  133.     _CHECKINT(&back[p],"Appel back_delete")
  134.     #endif
  135. #if HTS_DEBUG_CLOSESOCK
  136.     char info[256];
  137.     sprintf(info,"back_delete: #%d\n",p);
  138.     DEBUG_W2(info);
  139. #endif
  140.  
  141.     // LibΘrer tous les sockets, handles, buffers..
  142.     if (back[p].r.soc!=INVALID_SOCKET) {
  143. #if HTS_DEBUG_CLOSESOCK
  144.       DEBUG_W("back_delete: deletehttp\n");
  145. #endif
  146.       deletehttp(&back[p].r);
  147.       back[p].r.soc=INVALID_SOCKET;
  148.     }
  149.     if (back[p].r.adr!=NULL) {  // reste un bloc α dΘsallouer
  150.       freet(back[p].r.adr);
  151.       back[p].r.adr=NULL;
  152.     }
  153.     if (back[p].chunk_adr!=NULL) {  // reste un bloc α dΘsallouer
  154.       freet(back[p].chunk_adr);
  155.       back[p].chunk_adr=NULL;
  156.       back[p].chunk_size=0;
  157.       back[p].is_chunk=0;
  158.     }
  159.     if (back[p].r.is_file) {  // fermer fichier entrΘe
  160.       if (back[p].r.fp!=NULL) {
  161.         fclose(back[p].r.fp);
  162.         back[p].r.fp=NULL;
  163.       }
  164.     }
  165.     if (back[p].r.is_write) {     // ecriture directe
  166.       if (back[p].r.out!=NULL) {  // fermer fichier sortie
  167.         fclose(back[p].r.out);
  168.         back[p].r.out=NULL;
  169.       }
  170.       
  171.       /* Θcrire date "remote" */
  172.       if (strnotempty(back[p].url_sav))          // normalement existe si on a un fichier de sortie
  173.       if (strnotempty(back[p].r.lastmodified))   // last-modified existe
  174.       if (fexist(back[p].url_sav))          // ainsi que le fichier
  175.         set_filetime_rfc822(back[p].url_sav,back[p].r.lastmodified);
  176.  
  177.       /* executer commande utilisateur aprΦs chargement du fichier */
  178.       usercommand(0,NULL,back[p].url_sav);
  179.       back[p].r.is_write=0;
  180.     }
  181.     
  182.     // Tout nettoyer
  183.     bzero((char *)(&back[p]),sizeof(lien_back));  
  184.     back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  185.     
  186.     // Le plus important: libΘrer le champ
  187.     back[p].status=-1;
  188.   }
  189.   return 0;
  190. }
  191.  
  192. /* Space left on backing stack */
  193. int back_stack_available(lien_back* back,int back_max) {
  194.   int p=0,n=0;
  195.   for( ; p < back_max ; p++ )
  196.     if ( back[p].status == -1 )
  197.       n++;
  198.   return n;
  199. }
  200.  
  201. // ajouter un lien en backing
  202. int back_add(lien_back* back,int back_max,httrackp* opt,cache_back* cache,char* adr,char* fil,char* save,char* referer_adr,char* referer_fil,int test,short int* pass2_ptr) {
  203.   int p=0;
  204.  
  205.   // vΘrifier cohΘrence de adr et fil (non vide!)
  206.   if (strnotempty(adr)==0) {
  207.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  208.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: adr is empty for back_add"LF);
  209.     }
  210.     return -1;    // erreur!
  211.   }
  212.   if (strnotempty(fil)==0) {
  213.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  214.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: fil is empty for back_add"LF);
  215.     }
  216.     return -1;    // erreur!
  217.   }
  218.   // FIN vΘrifier cohΘrence de adr et fil (non vide!)
  219.  
  220.   // rechercher emplacement
  221.   while((p<back_max) && back[p].status!=-1) p++;
  222.   if (back[p].status==-1) {    // ok on a de la place
  223.     back[p].send_too[0]='\0';  // Θventuels paramΦtres supplΘmentaires α transmettre au serveur
  224.  
  225.     // ne sert α rien normalement
  226.     if (back[p].r.soc!=INVALID_SOCKET) {
  227. #if HTS_DEBUG_CLOSESOCK
  228.       DEBUG_W("back_add: deletehttp\n");
  229. #endif
  230.       deletehttp(&back[p].r);
  231.     }
  232.  
  233.     // effacer r
  234.     bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  235.  
  236.     // crΘer entrΘe
  237.     strcpy(back[p].url_adr,adr);
  238.     strcpy(back[p].url_fil,fil);
  239.     strcpy(back[p].url_sav,save);
  240.     back[p].pass2_ptr=pass2_ptr;
  241.     // copier referer si besoin
  242.     strcpy(back[p].referer_adr,"");
  243.     strcpy(back[p].referer_fil,"");
  244.     if ((referer_adr) && (referer_fil)) {       // existe
  245.       if ((strnotempty(referer_adr)) && (strnotempty(referer_fil))) {   // non vide
  246.         if (referer_adr[0]!='!') {    // non dΘtruit
  247.           if (strcmp(referer_adr,"file://")) {      // PAS file://
  248.             if (strcmp(referer_adr,"primary")) {      // pas referer 1er lien
  249.               strcpy(back[p].referer_adr,referer_adr);
  250.               strcpy(back[p].referer_fil,referer_fil);
  251.             }
  252.           }
  253.         }
  254.       }
  255.     }
  256.     // sav ne sert α rien pour le moment
  257.     back[p].r.size=0;                   // rien n'a encore ΘtΘ chargΘ
  258.     back[p].r.soc=INVALID_SOCKET;       // pas de socket
  259.     back[p].r.adr=NULL;                 // pas de bloc de mΘmoire
  260.     back[p].r.is_write=0;               // α priori stockage en mΘmoire
  261.     back[p].maxfile_html=opt->maxfile_html;
  262.     back[p].maxfile_nonhtml=opt->maxfile_nonhtml;
  263.     back[p].testmode=test;              // mode test?
  264.     if (!opt->http10)                 // option "forcer 1.0" dΘsactivΘe
  265.       back[p].http11=1;               // autoriser http/1.1
  266.     back[p].head_request=0;
  267.     if (strcmp(back[p].url_sav,BACK_ADD_TEST)==0)    // HEAD
  268.       back[p].head_request=1;
  269.     else if (strcmp(back[p].url_sav,BACK_ADD_TEST2)==0)    // test en GET
  270.       back[p].head_request=2;       // test en get
  271.  
  272.     // tester cache
  273.     if ((strcmp(adr,"file://"))           /* pas fichier */
  274.       && ( (!test) || (cache->type==1) )   /* cache prioritaire, laisser passer en test! */
  275.       && ( (strnotempty(save)) || (strcmp(fil,"/robots.txt")==0) ) ) {  // si en test on ne doit pas utiliser le cache sinon telescopage avec le 302..
  276.       //if ((!test) && (strcmp(adr,"file://")) 
  277.       //if ((!test) && (strncmp(adr,"ftp://",6)) && (strcmp(adr,"file://")) 
  278. #if HTS_FAST_CACHE
  279.       int hash_pos;
  280.       int hash_pos_return=0;
  281. #else
  282.       char* a=NULL;
  283. #endif
  284. #if HTS_FAST_CACHE
  285.       if (cache->hash) { 
  286. #else
  287.       if (cache->use) { 
  288. #endif
  289.         char buff[HTS_URLMAXSIZE*4];
  290. #if HTS_FAST_CACHE
  291.         strcpy(buff,adr); strcat(buff,fil);
  292.         hash_pos_return=inthash_read((hash_chain**)cache->hash,cache->hash_size,buff,(long int*)&hash_pos);
  293. #else
  294.         buff[0]='\0'; strcat(buff,"\n"); strcat(buff,adr); strcat(buff,"\n"); strcat(buff,fil); strcat(buff,"\n");
  295.         a=strstr(cache->use,buff);
  296. #endif
  297.         
  298.         // Ok, notΘ en cache->. mais bien prΘsent dans le cache ou sur disque?
  299. #if HTS_FAST_CACHE
  300.         if (hash_pos_return) {
  301. #else
  302.         if (a) {
  303. #endif
  304.           if (!test) {      // non mode test
  305. #if HTS_FAST_CACHE
  306.             int pos=hash_pos;
  307. #else
  308.             int pos=-1;
  309.             a+=strlen(buff);
  310.             sscanf(a,"%d",&pos);    // lire position
  311. #endif
  312.             if (pos<0) {    // pas de mise en cache data, vΘrifier existence
  313.               if (fsize(antislash(save)) <= 0) {  // fichier existe pas ou est vide!
  314. #if HTS_FAST_CACHE
  315.                 hash_pos_return=0;
  316. #else
  317.                 a=NULL;    
  318. #endif
  319.                 // dΘvalider car non prΘsent sur disque dans structure originale!!!
  320.                 // sinon, le fichier est ok α priori, mais on renverra un if-modified-since pour
  321.                 // en Ωtre s√r
  322.                 if (opt->norecatch) {              // tester norecatch
  323.                   if (!fexist(antislash(save))) {  // fichier existe pas mais dΘclarΘ: on l'a effacΘ
  324.                     FILE* fp=fopen(antislash(save),"wb");
  325.                     if (fp) fclose(fp);
  326.                     if (opt->log!=NULL) {
  327.                       fspc(opt->log,"warning"); fprintf(opt->log,"File must have been erased by user, ignoring: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  328.                     }
  329.                   }
  330.                 }
  331.               }
  332.             }
  333.           }
  334.         }
  335.         //
  336.       } else
  337. #if HTS_FAST_CACHE
  338.         hash_pos_return=0;
  339. #else
  340.         a=NULL;
  341. #endif
  342.  
  343.       // Existe pas en cache, ou bien pas de cache prΘsent
  344. #if HTS_FAST_CACHE
  345.       if (hash_pos_return) {  // OK existe en cache (et donnΘes aussi)!
  346. #else
  347.       if (a!=NULL) {  // OK existe en cache (et donnΘes aussi)!
  348. #endif
  349.         if (cache->type==1) {   // cache prioritaire (pas de test if-modified..)
  350.                                // dans ce cas on peut Θgalement lire des rΘponses cachΘes comme 404,302... 
  351.           // lire dans le cache
  352.           if (!test)
  353.             back[p].r=cache_read(opt,cache,adr,fil,save);
  354.           else
  355.             back[p].r=cache_read(opt,cache,adr,fil,NULL);       // charger en tΩte uniquement du cache
  356.           if (!back[p].r.location) 
  357.             back[p].r.location=back[p].location_buffer;
  358.           else {    /* recopier */
  359.             strcpy(back[p].location_buffer,back[p].r.location);
  360.             back[p].r.location=back[p].location_buffer;
  361.           }
  362.  
  363.           /* Interdiction taille par le wizard? --> dΘtruire */
  364.           if (back[p].r.statuscode != -1) {  // pas d'erreur de lecture
  365.             if (!back_checksize(opt,&back[p],0)) {
  366.               back[p].status=0;  // FINI
  367.               back[p].r.statuscode=-1;
  368.               if (!back[p].testmode)
  369.                 strcpy(back[p].r.msg,"Cached file skipped (too big)");
  370.               else
  371.                 strcpy(back[p].r.msg,"Test: Cached file skipped  (too big)");
  372.               return 0;
  373.             }
  374.           }
  375.  
  376.           if (back[p].r.statuscode != -1) {  // pas d'erreur de lecture
  377.             if ((opt->debug>0) && (opt->log!=NULL)) {
  378.               if (!test) {
  379.                 fspc(opt->log,"debug"); fprintf(opt->log,"File immediately loaded from cache: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  380.               } else {
  381.                 fspc(opt->log,"debug"); fprintf(opt->log,"File immediately tested from cache: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  382.               }
  383.             }
  384.             back[p].r.notmodified=1;    // fichier non modifiΘ
  385.             back[p].status=0;  // OK prΩt
  386.             //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode);
  387.             return 0;
  388.           } else {  // erreur
  389.             // effacer r
  390.             bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  391.             // et continuer (chercher le fichier)
  392.           }
  393.           
  394.         } else if (cache->type==2) {    // si en cache, demander de tester If-Modified-Since
  395.           htsblk* r=cache_header(opt,cache,adr,fil);
  396.  
  397.           /* Interdiction taille par le wizard? */
  398.           {
  399.             LLint save_totalsize=back[p].r.totalsize;
  400.             back[p].r.totalsize=r->totalsize;
  401.             if (!back_checksize(opt,&back[p],1)) {
  402.               r=NULL;
  403.               //
  404.               back[p].status=0;  // FINI
  405.               deletehttp(&back[p].r); back[p].r.soc=INVALID_SOCKET;
  406.               if (!back[p].testmode)
  407.                 strcpy(back[p].r.msg,"File too big");
  408.               else
  409.                 strcpy(back[p].r.msg,"Test: File too big");
  410.               return 0;
  411.             }
  412.             back[p].r.totalsize=save_totalsize;
  413.           }
  414.           
  415.           if (r) {
  416.             if (r->statuscode==200) {     // uniquement des 200 (OK)
  417.               if (strnotempty(r->etag)) {  // ETag (RFC2616)
  418.                 if (strnotempty(r->lastmodified))
  419.                   sprintf(back[p].send_too,"If-None-Match: %s\r\nIf-Modified-Since: %s\r\n",r->etag,r->lastmodified);
  420.                 else
  421.                   sprintf(back[p].send_too,"If-None-Match: %s\r\n",r->etag);
  422.               }
  423.               else if (strnotempty(r->lastmodified))
  424.                 sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",r->lastmodified);
  425.               else if (strnotempty(cache->lastmodified))
  426.                 sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",cache->lastmodified);
  427.  
  428.               /* this is an update of a file */
  429.               if (strnotempty(back[p].send_too))
  430.                 back[p].is_update=1;
  431.  
  432.             }
  433.              /* else if (strnotempty(cache->lastmodified))
  434.               sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",cache->lastmodified);
  435.              */
  436.           }
  437. #if DEBUGCA
  438.           printf("..is modified test %s\n",back[p].send_too);
  439. #endif
  440.         } 
  441.         // Okay, pas trouvΘ dans le cache
  442.         // Et si le fichier existe sur disque?
  443.         // Pas dans le cache: fichier n'a pas ΘtΘ transfΘrΘ du tout, donc pas sur disque?
  444.       } else {
  445.         if (fexist(save)) {    // fichier existe? aghl!
  446.           LLint sz=fsize(save);
  447.           // Bon, lα il est possible que le fichier ait ΘtΘ partiellement transfΘrΘ
  448.           // (s'il l'avait ΘtΘ en totalitΘ il aurait ΘtΘ inscrit dans le cache ET existerait sur disque)
  449.           // PAS de If-Modified-Since, on a pas connaissance des donnΘes α la date du cache
  450.           // On demande juste les donnΘes restantes si le date est valide (206), tout sinon (200)
  451.           if ((ishtml(save) != 1) && (ishtml(back[p].url_fil)!=1)) {   // NON HTML (liens changΘs!!)
  452.             if (sz>0) {    // Fichier non vide? (question bΩte, sinon on transfert tout!)
  453.               if (strnotempty(cache->lastmodified)) {     /* pas de If-.. possible */
  454.                 /*if ( (!opt->http10) && (strnotempty(cache->lastmodified)) ) { */    /* ne pas forcer 1.0 */
  455. #if DEBUGCA
  456.                 printf("..if unmodified since %s size "LLintP"\n",cache->lastmodified,(LLint)sz);
  457. #endif
  458.                 if ((opt->debug>1) && (opt->log!=NULL)) {
  459.                   fspc(opt->log,"debug"); fprintf(opt->log,"File partially present ("LLintP" bytes): %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); test_flush;
  460.                 }
  461.                 
  462.                 /* impossible - don't have etag or date
  463.                 if (strnotempty(back[p].r.etag)) {  // ETag (RFC2616)
  464.                 sprintf(back[p].send_too,"If-None-Match: %s\r\n",back[p].r.etag);
  465.                 back[p].http11=1;    // En tΩte 1.1
  466.                 } else if (strnotempty(back[p].r.lastmodified)) {
  467.                 sprintf(back[p].send_too,"If-Unmodified-Since: %s\r\n",back[p].r.lastmodified);
  468.                 back[p].http11=1;    // En tΩte 1.1
  469.                 } else 
  470.                 */
  471.                 if (strlen(cache->lastmodified)) {
  472.                   sprintf(back[p].send_too,
  473.                     "If-Unmodified-Since: %s\r\nRange: bytes="LLintP"-\r\n"
  474.                     ,cache->lastmodified,(LLint)sz);
  475.                   back[p].http11=1;    // En tΩte 1.1
  476.                   back[p].range_req_size=sz;
  477.                 } else {
  478.                   if ((opt->debug>0) && (opt->errlog!=NULL)) {
  479.                     fspc(opt->log,"warning"); fprintf(opt->log,"Could not find timestamp for partially present file, restarting (lost "LLintP" bytes): %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); test_flush;
  480.                   }
  481.                 }
  482.                 
  483.               } else { 
  484.                 if ((opt->debug>0) && (opt->errlog!=NULL)) {
  485.                   fspc(opt->errlog,"warning");
  486.                   /*
  487.                   if (opt->http10)
  488.                   fprintf(opt->errlog,"File partially present (%d bytes) retransfered due to HTTP/1.0 settings: %s%s"LF,sz,back[p].url_adr,back[p].url_fil);
  489.                   else
  490.                   */
  491.                   fprintf(opt->errlog,"File partially present ("LLintP" bytes) retransfered due to lack of cache: %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); 
  492.                   test_flush;
  493.                 }
  494.                 /* Sinon requΩte normale... */
  495.                 back[p].http11=0;
  496.               }
  497.             } else if (opt->norecatch) {              // tester norecatch
  498.               filenote(save,NULL);       // ne pas purger tout de mΩme
  499.               back[p].status=0;  // OK prΩt
  500.               back[p].r.statuscode=-1;  // erreur
  501.               strcpy(back[p].r.msg,"Null-size file not recaught");
  502.               return 0;
  503.             }
  504.           } else {
  505.             if ((opt->debug>0) && (opt->errlog!=NULL)) {
  506.               fspc(opt->errlog,"warning");
  507.               fprintf(opt->errlog,"HTML file ("LLintP" bytes) retransfered due to lack of cache: %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); 
  508.               test_flush;
  509.             }
  510.             /* Sinon requΩte normale... */
  511.             back[p].http11=0;
  512.           }
  513.         }
  514.       }
  515.     }
  516.  
  517.  
  518.     {
  519.       ///htsblk r;   non directement dans la structure-rΘponse!
  520.       T_SOC soc;
  521.       
  522.       // ouvrir liaison, envoyer requΦte
  523.       // ne pas traiter ou recevoir l'en tΩte immΘdiatement
  524.       bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  525.       // recopier proxy
  526.       bcopy((char*) &opt->proxy,(char*) &(back[p].r.req.proxy), sizeof(opt->proxy));
  527.       // et user-agent
  528.       strcpy(back[p].r.req.user_agent,opt->user_agent);
  529.       strcpy(back[p].r.req.lang_iso,opt->lang_iso);
  530.       back[p].r.req.user_agent_send=opt->user_agent_send;
  531.       // et http11
  532.       back[p].r.req.http11=back[p].http11;
  533.  
  534.       // mode ftp, court-circuit!
  535.       if (strncmp(back[p].url_adr,"ftp://",6)==0) {
  536.         if (back[p].testmode) {
  537.           if ((opt->debug>1) && (opt->errlog!=NULL)) {
  538.             fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: forbidden test with ftp link for back_add"LF);
  539.           }
  540.           return -1;    // erreur pas de test permis
  541.         }
  542.         if (!(back[p].r.req.proxy.active && opt->ftp_proxy)) { // connexion directe, gΘrΘe en thread
  543.           back[p].status=1000;   // connexion ftp
  544. #if USE_BEGINTHREAD
  545.           launch_ftp(&(back[p]));
  546. #else
  547.           {
  548.             char nid[32];
  549.             sprintf(nid,"htsftp%d-in_progress.lock",p);
  550.             strcpy(back[p].location_buffer,fconcat(opt->path_log,nid));
  551.           }
  552.           launch_ftp(&(back[p]),back[p].location_buffer,opt->exec);
  553. #endif
  554.           return 0;
  555.         }
  556.       }
  557.       
  558. #if HTS_XGETHOST
  559. #if HDEBUG
  560.       printf("back_solve..\n");
  561. #endif
  562.       back[p].status=101;    // tentative de rΘsolution du nom de host
  563.       soc=INVALID_SOCKET;    // pas encore ouverte
  564.       back_solve(&back[p]);  // prΘparer
  565.       if (host_wait(&back[p])) {  // prΩt, par ex fichier ou dispo dans dns
  566. #if HDEBUG
  567.       printf("ok, dns cache ready..\n");
  568. #endif
  569.         soc=http_xfopen(0,0,0,back[p].send_too,adr,fil,&(back[p].r));
  570.         if (soc==INVALID_SOCKET) {
  571.           back[p].status=0;  // fini, erreur
  572.         }
  573.       }
  574. //
  575. #else
  576. //
  577. #if CNXDEBUG
  578.       printf("XFopen..\n");
  579. #endif
  580.  
  581.       if (strnotempty(back[p].send_too))    // envoyer un if-modified-since
  582. #if HTS_XCONN
  583.       soc=http_xfopen(0,0,0,back[p].send_too,adr,fil,&(back[p].r));
  584. #else
  585.       soc=http_xfopen(0,0,1,back[p].send_too,adr,fil,&(back[p].r));
  586. #endif
  587.       else
  588. #if HTS_XCONN
  589.         soc=http_xfopen(test,0,0,NULL,adr,fil,&(back[p].r));
  590. #else
  591.       soc=http_xfopen(test,0,1,NULL,adr,fil,&(back[p].r));
  592. #endif
  593. #endif
  594.       if (opt->timeout>0) {    // gestion du opt->timeout
  595.         back[p].timeout=opt->timeout;
  596.         back[p].timeout_refresh=time_local();
  597.       } else {
  598.         back[p].timeout=-1;    // pas de gestion (default)
  599.       }
  600.       
  601.       if (opt->rateout>0) {    // gestion d'un taux minimum de transfert tolΘrΘ
  602.         back[p].rateout=opt->rateout;
  603.         back[p].rateout_time=time_local();
  604.       } else {
  605.         back[p].rateout=-1;    // pas de gestion (default)
  606.       }
  607.  
  608.       // Note: on charge les code-page erreurs (erreur 404, etc) dans le cas o∙ cela est
  609.       // rattrapable (exemple: 301,302 moved xxx -> refresh sur la page!)
  610.       //if ((back[p].statuscode!=200) || (soc<0)) { // ERREUR HTTP/autre
  611.  
  612. #if CNXDEBUG
  613. printf("Xfopen ok, poll..\n");
  614. #endif
  615.  
  616. #if HTS_XGETHOST
  617.     if (soc!=INVALID_SOCKET)
  618.       if (back[p].status==101) {  // pas d'erreur
  619.         if (!back[p].r.is_file)
  620.           back[p].status=100;   // connexion en cours
  621.         else
  622.           back[p].status=1;     // fichier
  623.       }
  624.  
  625. #else
  626.       if (soc==INVALID_SOCKET) { // erreur socket
  627.         back[p].status=0;    // FINI
  628.         //if (back[p].soc!=INVALID_SOCKET) deletehttp(back[p].soc);
  629.         back[p].r.soc=INVALID_SOCKET;
  630.       } else {
  631.         if (!back[p].r.is_file)
  632. #if HTS_XCONN
  633.           back[p].status=100;   // connexion en cours
  634. #else
  635.           back[p].status=99;    // chargement en tΩte en cours
  636. #endif
  637.         else
  638.           back[p].status=1;     // chargement fichier
  639. #if BDEBUG==1
  640.         printf("..loading header\n");
  641. #endif
  642.       }
  643. #endif
  644.       
  645.     }
  646.  
  647.  
  648.     // note: si il y a erreur (404,etc) status=2 (terminΘ/Θchec) mais
  649.     // le lien est considΘrΘ comme traitΘ
  650.     //if (back[p].soc<0)  // erreur
  651.     //  return -1;
  652.  
  653.     return 0;
  654.   } else {
  655.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  656.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: no space left in stack for back_add"LF);
  657.     }
  658.     return -1;    // plus de place
  659.   }
  660. }
  661.  
  662.  
  663.  
  664. #if HTS_XGETHOST
  665. #if USE_BEGINTHREAD
  666. // lancement multithread du robot
  667. PTHREAD_TYPE Hostlookup(void* iadr_p) {
  668.   char iadr[256];
  669.   t_dnscache* cache=_hts_cache();  // adresse du cache
  670.   t_hostent* hp;
  671.   int error_found=0;
  672.  
  673.   // recopier (aprΦs id:pass)
  674. #if DEBUGDNS 
  675.   printf("resolv in background: %s\n",jump_identification(iadr_p));
  676. #endif
  677.   strcpy(iadr,jump_identification(iadr_p));
  678.   // couper Θventuel :
  679.   {
  680.     char *a;
  681.     if ( (a=strchr(iadr,':')) )
  682.       *a='\0';
  683.   }
  684.   freet(iadr_p);
  685.  
  686.   // attendre que le cache dns soit prΩt
  687.   while(_hts_lockdns(-1));  // attendre libΘration
  688.   _hts_lockdns(1);          // locker
  689.   while(cache->n) {
  690.     if (strcmp(cache->iadr,iadr)==0) {
  691.       error_found=1;
  692.     }
  693.     cache=cache->n;    // calculer queue
  694.   }
  695.   if (strcmp(cache->iadr,iadr)==0) {
  696.     error_found=1;
  697.   }
  698.  
  699.   if (!error_found) {
  700.     // en gros copie de hts_gethostbyname sans le return
  701.     cache->n=(t_dnscache*) calloct(1,sizeof(t_dnscache));
  702.     if (cache->n!=NULL) {
  703.       strcpy(cache->n->iadr,iadr);
  704.       cache->n->host_length=0;        /* pour le moment rien */
  705.       cache->n->n=NULL;
  706.       _hts_lockdns(0);          // dΘlocker
  707.       
  708.       /* resolve */
  709. #if DEBUGDNS 
  710.       printf("gethostbyname() in progress for %s\n",iadr);
  711. #endif
  712.       hp=gethostbyname(iadr);  // rΘsolution IP
  713.       
  714.       /* okay, result */
  715.       if (hp!=NULL) {
  716.         bcopy(hp->h_addr,cache->n->host_addr,hp->h_length);       // write first
  717.         cache->n->host_length=hp->h_length;                       // then write this
  718.       } else {
  719.         cache->n->host_addr[0]='\0';
  720.         cache->n->host_length=-1;             // dΘclarer erreur dans le dns
  721.       }
  722.     } else 
  723.     _hts_lockdns(0);          // dΘlocker
  724.   } else {
  725. #if DEBUGDNS 
  726.     printf("aborting resolv for %s (found)\n",iadr);
  727. #endif
  728.     _hts_lockdns(0);          // dΘlocker
  729.   }
  730.   // fin de copie de hts_gethostbyname
  731.  
  732. #if DEBUGDNS 
  733.   printf("quitting resolv for %s (result: %d)\n",iadr,(cache->n!=NULL)?cache->n->host_length:(-999));
  734. #endif
  735.  
  736.   return PTHREAD_RETURN;     /* _endthread implied  */
  737. }
  738. #endif
  739.  
  740. // attendre que le host (ou celui du proxy) ait ΘtΘ rΘsolu
  741. // si c'est un fichier, la rΘsolution est immΘdiate
  742. // idem pour ftp://
  743. void back_solve(lien_back* back) {
  744.   if ((strcmp(back->url_adr,"file://")) && (strncmp(back->url_adr,"ftp://",6))) {
  745.   //## if (back->url_adr[0]!=lOCAL_CHAR) {  // qq chose α prΘparer
  746.     char* a;
  747.     if (!(back->r.req.proxy.active))
  748.       a=back->url_adr;
  749.     else
  750.       a=back->r.req.proxy.name;
  751.     if (!hts_dnstest(a)) {   // non encore testΘ!..
  752.       // inscire en thread
  753. #if HTS_WIN
  754.       // Windows
  755. #if USE_BEGINTHREAD
  756.       {
  757.         char* p = calloct(strlen(a)+2,1);
  758.         if (p) {
  759.           strcpy(p,a);
  760.           _beginthread( Hostlookup , 0, p );
  761.         }
  762.       }
  763. #else
  764.       /*t_hostent* h=*/
  765.       /*hts_gethostbyname(a);*/  // calcul
  766. #endif
  767. #else
  768. #if USE_BEGINTHREAD
  769.         char* p = calloct(strlen(a)+2,1);
  770.         if (p) {
  771.           strcpy(p,a);
  772.           _beginthread( Hostlookup , 0, p );
  773.         }
  774. #else
  775.       // Sous Unix, le gethostbyname() est bloquant..
  776.       /*t_hostent* h=*/
  777.       /*hts_gethostbyname(a);*/  // calcul
  778. #endif
  779. #endif
  780.     }
  781.   }
  782. }
  783.  
  784. // dΘtermine si le host a pu Ωtre rΘsolu
  785. int host_wait(lien_back* back) {
  786.   if ((strcmp(back->url_adr,"file://")) && (strncmp(back->url_adr,"ftp://",6))) {
  787.   //## if (back->url_adr[0]!=lOCAL_CHAR) {
  788.     if (!(back->r.req.proxy.active)) {
  789.       return (hts_dnstest(back->url_adr));
  790.     } else {
  791.       return (hts_dnstest(back->r.req.proxy.name));      
  792.     }
  793.   } else return 1;    // prΩt, fichier local
  794. }
  795. #endif
  796.  
  797.  
  798. // Θlimine les fichiers non html en backing
  799. // cleanup non-html files in backing to save backing space
  800. // and allow faster "save in cache" operation
  801. void back_clean(httrackp* opt,cache_back* cache,lien_back* back,int back_max) {
  802.   int i;
  803.   for(i=0;i<back_max;i++) {
  804.     if (back[i].status == 0) {                                   // ready
  805.       if (!back[i].testmode) {                                   // not test mode
  806.         if (strnotempty(back[i].url_sav)) {                      // filename exists
  807.           if (back[i].r.is_write) {                              // not in memory (on disk, ready)
  808.             if (back[i].r.size>0) {                              // size>0
  809.               if (back[i].r.statuscode==200) {                   // HTTP "OK"
  810.                 if (!is_hypertext_mime(back[i].r.contenttype)) { // not HTML/hypertext
  811.                   if (back[i].pass2_ptr) {
  812.                     cache_mayadd(opt,cache,&back[i].r,back[i].url_adr,back[i].url_fil,back[i].url_sav);
  813.                     *back[i].pass2_ptr=-1;  // Done!
  814.                     back_delete(back,i);    // Delete backing entry
  815.                     HTS_STAT.stat_bytes+=back[i].r.size;
  816.                     HTS_STAT.stat_files++;
  817.                     if ( (!back[i].r.notmodified) && (opt->is_update) ) { 
  818.                       HTS_STAT.stat_updated_files++;       // page modifiΘe
  819.                     }
  820.                   }
  821.                 }
  822.               }
  823.             }
  824.           }
  825.         }
  826.       }
  827.     }
  828.   }            
  829. }
  830.  
  831.  
  832. // attente (gestion des buffers des sockets)
  833. void back_wait(lien_back* back,int back_max,httrackp* opt,cache_back* cache,double stat_timestart) {
  834.   int i;
  835.   T_SOC nfds=INVALID_SOCKET;
  836.   fd_set fds,fds_c,fds_e;     // fds pour lecture, connect (write), et erreur
  837.   struct timeval tv;
  838.   int do_wait=0;
  839.   int gestion_timeout=0;
  840.   int busy=0;    // pas de donnΘes pour le moment   
  841. #if HTS_ANALYSTE
  842.   int max_loop=8;  // nombre de boucles max α parcourir..
  843.   int max_loop_chk=0;
  844. #else
  845.   int max_loop=8;  // nombre de boucles max α parcourir..
  846. #endif
  847.  
  848.  
  849. #if 1
  850.   // Cleanup the stack to save space!
  851.   back_clean(opt,cache,back,back_max);
  852. #endif
  853.  
  854.   // recevoir tant qu'il y a des donnΘes (avec un maximum de max_loop boucles)
  855.   do_wait=0;
  856.   gestion_timeout=0;
  857.   do {
  858.     int max_c;
  859.     busy=0;
  860.  
  861.     check_rate(stat_timestart,opt->maxrate);    // vΘrifier taux de transfert
  862.     // inscrire les sockets actuelles, et rechercher l'ID la plus ΘlevΘe
  863.     FD_ZERO(&fds);
  864.     FD_ZERO(&fds_c);
  865.     FD_ZERO(&fds_e);
  866.  
  867.     max_c=1;
  868.     for(i=0;i<back_max;i++) {
  869.  
  870.       // en cas de gestion du connect prΘemptif
  871. #if HTS_XCONN
  872.       if (back[i].status==100) {      // connexion
  873.         do_wait=1;
  874.  
  875.         // noter socket write
  876.         FD_SET(back[i].r.soc,&fds_c);
  877.         
  878.         // noter socket erreur
  879.         FD_SET(back[i].r.soc,&fds_e);
  880.  
  881.         // calculer max
  882.         if (max_c) {
  883.           max_c=0;
  884.           nfds=back[i].r.soc;
  885.         } else if (back[i].r.soc>nfds) {
  886.           // ID socket la plus ΘlevΘe
  887.           nfds=back[i].r.soc;
  888.         }
  889.         
  890.       } else
  891. #endif
  892. #if HTS_XGETHOST
  893.       if (back[i].status==101) {      // attente
  894.         // rien α faire..
  895.       } else
  896. #endif
  897.       // poll pour la lecture sur les sockets
  898.       if ((back[i].status>0) && (back[i].status<100)) {  // en rΘception http
  899.             
  900. #if BDEBUG==1
  901.         //printf("....socket in progress: %d\n",back[i].r.soc);
  902. #endif
  903.         // non local et non ftp
  904.         if (strncmp(back[i].url_adr,"file://",7)) {
  905.         //## if (back[i].url_adr[0]!=lOCAL_CHAR) {
  906.           
  907.           // vΘrification de sΘcuritΘ
  908.           if ((back[i].r.soc!=INVALID_SOCKET) && (!back[i].r.is_file)) {  // hey, you never know..
  909.             do_wait=1;
  910.             
  911.             // noter socket read
  912.             FD_SET(back[i].r.soc,&fds);
  913.             
  914.             // noter socket error
  915.             FD_SET(back[i].r.soc,&fds_e);
  916.             
  917.             // calculer max
  918.             if (max_c) {
  919.               max_c=0;
  920.               nfds=back[i].r.soc;
  921.             } else if (back[i].r.soc>nfds) {
  922.               // ID socket la plus ΘlevΘe
  923.               nfds=back[i].r.soc;
  924.             }
  925.           } 
  926. #if WIDE_DEBUG
  927.           else {
  928.             DEBUG_W("PANIC!!! Socket is invalid in a poll test!\n");
  929.           }
  930. #endif
  931.           
  932.         }
  933.         
  934.       }
  935.     }    
  936.     nfds++;
  937.     
  938.     if (do_wait) {  // attendre
  939.       // temps d'attente max: 2.5 seconde
  940.       tv.tv_sec=HTS_SOCK_SEC;
  941.       tv.tv_usec=HTS_SOCK_MS;
  942.       
  943. #if BDEBUG==1
  944.       printf("..select\n");
  945. #endif
  946.       
  947.       // poller les sockets-attention au noyau sous Unix..
  948. #if HTS_WIDE_DEBUG    
  949.       DEBUG_W("select\n");
  950. #endif
  951.       select(nfds,&fds,&fds_c,&fds_e,&tv);
  952. #if HTS_WIDE_DEBUG    
  953.       DEBUG_W("select done\n");
  954. #endif      
  955.     }
  956.      
  957.     // recevoir les donnΘes arrivΘes
  958.     for(i=0;i<back_max;i++) {
  959.       
  960.       if (back[i].status>0) {
  961.         if ((back[i].r.soc!=INVALID_SOCKET) && (!back[i].r.is_file)) {  // hey, you never know..
  962.           int err;
  963.           // erreur?
  964.           err=FD_ISSET(back[i].r.soc,&fds_e);        
  965.           if (err) {
  966.             if (back[i].r.soc!=INVALID_SOCKET) {
  967. #if HTS_DEBUG_CLOSESOCK
  968.               DEBUG_W("back_wait: deletehttp\n");
  969. #endif
  970.               deletehttp(&back[i].r);
  971.             }
  972.             back[i].r.soc=INVALID_SOCKET;
  973.             back[i].r.statuscode=-4;
  974.             if (back[i].status==100)
  975.               strcpy(back[i].r.msg,"Connect Error");
  976.             else
  977.               strcpy(back[i].r.msg,"Receive Error");
  978.             back[i].status=0;  // terminΘ
  979.           }
  980.         }
  981.       }
  982.  
  983.       // ---- FLAG WRITE MIS A UN?: POUR LE CONNECT
  984.       if (back[i].status==100) {   // attendre connect
  985.         int dispo=0;
  986.         // vΘrifier l'existance de timeout-check
  987.         if (!gestion_timeout)
  988.           if (back[i].timeout>0)
  989.             gestion_timeout=1;
  990.           
  991.         // connectΘ?
  992.         dispo=FD_ISSET(back[i].r.soc,&fds_c);
  993.         if (dispo) {    // ok
  994.           busy=1;
  995. #if BDEBUG==1
  996.           printf("..connect ok on socket %d\n",back[i].r.soc);
  997. #endif
  998.           /* limit nb. connections/seconds to avoid server overload */
  999.           if (opt->maxconn>0) {
  1000.             Sleep(1000/opt->maxconn);
  1001.           }
  1002.  
  1003.           if (back[i].timeout>0) {    // refresh timeout si besoin est
  1004.             back[i].timeout_refresh=time_local();
  1005.           }
  1006.           if (back[i].rateout>0) {    // le taux de transfert de base sur le dΘbut de la connexion
  1007.             back[i].rateout_time=time_local();
  1008.           }
  1009.           // envoyer header
  1010.           //if (strcmp(back[i].url_sav,BACK_ADD_TEST)!=0)    // vrai get
  1011.           if (!back[i].head_request)
  1012.             http_sendhead(opt->cookie,0,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1013.           else if (back[i].head_request==2)  // test en GET!
  1014.             http_sendhead(opt->cookie,0,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1015.           else        // test!
  1016.             http_sendhead(opt->cookie,1,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1017.           back[i].status=99;  // attendre en tΩte maintenant
  1018.         }
  1019.  
  1020.         // attente gethostbyname
  1021.       } 
  1022. #if HTS_XGETHOST
  1023.       else if (back[i].status==101) {  // attendre gethostbyname
  1024. #if DEBUGDNS 
  1025.         //printf("status 101 for %s\n",back[i].url_adr);
  1026. #endif
  1027.  
  1028.         if (!gestion_timeout)
  1029.           if (back[i].timeout>0)
  1030.             gestion_timeout=1;
  1031.  
  1032.         if (host_wait(&back[i])) {    // prΩt
  1033.           back[i].status=100;        // attente connexion
  1034.           if (back[i].timeout>0) {    // refresh timeout si besoin est
  1035.             back[i].timeout_refresh=time_local();
  1036.           }
  1037.           if (back[i].rateout>0) {    // le taux de transfert de base sur le dΘbut de la connexion
  1038.             back[i].rateout_time=time_local();
  1039.           }
  1040.  
  1041.           back[i].r.soc=http_xfopen(0,0,0,back[i].send_too,back[i].url_adr,back[i].url_fil,&(back[i].r));
  1042.           if (back[i].r.soc==INVALID_SOCKET) {
  1043.             back[i].status=0;  // fini, erreur
  1044.             if (back[i].r.soc!=INVALID_SOCKET) {
  1045. #if HTS_DEBUG_CLOSESOCK
  1046.               DEBUG_W("back_wait(2): deletehttp\n");
  1047. #endif
  1048.               deletehttp(&back[i].r);
  1049.             }
  1050.             back[i].r.soc=INVALID_SOCKET;
  1051.             back[i].r.statuscode=-5;
  1052.             if (strnotempty(back[i].r.msg)==0) 
  1053.               strcpy(back[i].r.msg,"Unable to establish host name");
  1054.           }
  1055.         }
  1056.         
  1057.  
  1058.       // ---- FLAG READ MIS A UN?: POUR LA RECEPTION
  1059.       }
  1060. #endif
  1061. #if USE_BEGINTHREAD
  1062.       // ..rien α faire, c'est magic les threads
  1063. #else
  1064.       else if (back[i].status==1000) {  // en rΘception ftp
  1065.         if (!fexist(back[i].location_buffer)) {    // terminΘ
  1066.           FILE* fp;
  1067.           fp=fopen(fconcat(back[i].location_buffer,".ok"),"rb");
  1068.           if (fp) {
  1069.             int j=0;
  1070.             fscanf(fp,"%d ",&(back[i].r.statuscode));
  1071.             while(!feof(fp)) {
  1072.               int c = fgetc(fp);
  1073.               if (c!=EOF)
  1074.                 back[i].r.msg[j++]=c;
  1075.             }
  1076.             back[i].r.msg[j++]='\0';
  1077.             fclose(fp);
  1078.             remove(fconcat(back[i].location_buffer,".ok"));
  1079.             strcpy(fconcat(back[i].location_buffer,".ok"),"");
  1080.           } else {
  1081.             strcpy(back[i].r.msg,"Unknown ftp result, check if file is ok");
  1082.             back[i].r.statuscode=-1;
  1083.           }
  1084.           back[i].status=0;
  1085.         }
  1086.       }
  1087. #endif
  1088.       else if ((back[i].status>0) && (back[i].status<1000)) {  // en rΘception http
  1089.         int dispo=0;
  1090.         
  1091.         // vΘrifier l'existance de timeout-check
  1092.         if (!gestion_timeout)
  1093.           if (back[i].timeout>0)
  1094.             gestion_timeout=1;
  1095.           
  1096.           // donnΘes dispo?
  1097.           //## if (back[i].url_adr[0]!=lOCAL_CHAR)
  1098.           if (strcmp(back[i].url_adr,"file://"))
  1099.             dispo=FD_ISSET(back[i].r.soc,&fds);
  1100.           else dispo=1;
  1101.           
  1102.           if (dispo) {    // donnΘes dispo
  1103.             LLint retour_fread;
  1104.             busy=1;    // on rΘcupΦre encore
  1105. #if BDEBUG==1
  1106.             printf("..data available on socket %d\n",back[i].r.soc);
  1107. #endif
  1108.  
  1109.             
  1110.             // Various hacks to limit re-transfers when updating a mirror
  1111.             if (opt->sizehack) {
  1112.               // We have request for a partial file (with a 'Range: NNN-' header)
  1113.               // and received a complete file notification (200), with 'Content-length: NNN'
  1114.               // it might be possible that we had the complete file
  1115.               // this is the case in *most* cases, so break the connection
  1116.               if (back[i].r.is_write==0) {  // mode mΘmoire
  1117.                 if (back[i].r.adr==NULL) {  // rien n'a ΘtΘ Θcrit
  1118.                   if (!back[i].testmode) {  // pas mode test
  1119.                     if (strnotempty(back[i].url_sav)) {
  1120.                       if (strcmp(back[i].url_fil,"/robots.txt")) {
  1121.                         if (back[i].r.statuscode==200) {  // 'OK'
  1122.                           if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1123.                             
  1124.                             if (back[i].r.statuscode==200) {      // "OK"
  1125.                               if (back[i].range_req_size>0) {     // but Range: requested
  1126.                                 if (back[i].range_req_size == back[i].r.totalsize) {    // And same size
  1127. #if HTS_DEBUG_CLOSESOCK
  1128.                                   DEBUG_W("back_wait(skip_range): deletehttp\n");
  1129. #endif
  1130.                                   deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1131.                                   back[i].status=0;    // READY
  1132.                                   back[i].r.size=back[i].r.totalsize;
  1133.                                   filenote(back[i].url_sav,NULL);
  1134.                                   // back[i].r.statuscode=304;     // NOT MODIFIED
  1135.                                   if ((opt->debug>1) && (opt->log!=NULL)) {
  1136.                                     fspc(opt->log,"debug"); fprintf(opt->log,"File seems complete (reget failed), breaking connection: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1137.                                   }
  1138.                                 }
  1139.                               }
  1140.                             }
  1141.                             
  1142.                           }
  1143.                         }
  1144.                       }
  1145.                     }
  1146.                   }
  1147.                 }
  1148.               }
  1149.             }
  1150.             // END - Various hacks to limit re-transfers when updating a mirror
  1151.  
  1152.  
  1153.  
  1154. #if HTS_DIRECTDISK
  1155.             // Court-circuit:
  1156.             // Peut-on stocker le fichier directement sur disque?
  1157.             // Ahh que ca serait vachement mieux et que ahh que la mΘmoire vous dit merci!
  1158.             if (back[i].status) {
  1159.               if (back[i].r.is_write==0) {  // mode mΘmoire
  1160.                 if (back[i].r.adr==NULL) {  // rien n'a ΘtΘ Θcrit
  1161.                   if (!back[i].testmode) {  // pas mode test
  1162.                     if (strnotempty(back[i].url_sav)) {
  1163.                       if (strcmp(back[i].url_fil,"/robots.txt")) {
  1164.                         if (back[i].r.statuscode==200) {  // 'OK'
  1165.                           if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1166.                             if (opt->getmode&2) {    // on peut ecrire des non html
  1167.                               back[i].r.is_write=1;    // Θcrire
  1168.                               back[i].r.out=filecreate(back[i].url_sav);
  1169. #if HDEBUG
  1170.                               printf("direct-disk: %s\n",back[i].url_sav);
  1171. #endif
  1172.                               if ((opt->debug>1) && (opt->log!=NULL)) {
  1173.                                 fspc(opt->log,"debug"); fprintf(opt->log,"File received from net to disk: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1174.                               }
  1175.                               
  1176.                               if (back[i].r.out==NULL) {
  1177.                                 back[i].r.is_write=0;    // erreur, abandonner
  1178. #if HDEBUG
  1179.                                 printf("..error!\n");
  1180. #endif
  1181.                               }
  1182. #if HTS_WIN==0
  1183.                               else chmod(back[i].url_sav,HTS_ACCESS_FILE);      
  1184. #endif          
  1185.                             } else {  // on coupe tout!
  1186.                               if ((opt->debug>1) && (opt->log!=NULL)) {
  1187.                                 fspc(opt->log,"debug"); fprintf(opt->log,"File cancelled (non HTML): %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1188.                               }
  1189.                               back[i].status=0;  // terminΘ
  1190.                               if (!back[i].testmode)
  1191.                                 back[i].r.statuscode=-10;    // EUHH CANCEL
  1192.                               else
  1193.                                 back[i].r.statuscode=-10;    // "TEST OK"
  1194.                               if (back[i].r.soc!=INVALID_SOCKET) {
  1195. #if HTS_DEBUG_CLOSESOCK
  1196.                                 DEBUG_W("back_wait(3): deletehttp\n");
  1197. #endif
  1198.                                 deletehttp(&back[i].r);
  1199.                               }
  1200.                               back[i].r.soc=INVALID_SOCKET;
  1201.                             }
  1202.                           }
  1203.                         }
  1204.                       }
  1205.                     }
  1206.                   }
  1207.                 }
  1208.               }
  1209.             }
  1210. #endif              
  1211.  
  1212.             // rΘception de donnΘes depuis socket ou fichier
  1213.             if (back[i].status) {
  1214.               if (back[i].status==99)  // recevoir caractΦre par caractΦre
  1215.                 retour_fread=http_xfread1(&(back[i].r),0);
  1216.               else if (back[i].status==98) { // recevoir longueur chunk en hexa caractΦre par caractΦre
  1217.                 // backuper pour lire dans le buffer chunk
  1218.                 htsblk r;
  1219.                 bcopy((char*) &(back[i].r), (char*) &r, sizeof(htsblk));
  1220.                 back[i].r.is_write=0;                   // mΘmoire
  1221.                 back[i].r.adr=back[i].chunk_adr;        // adresse
  1222.                 back[i].r.size=back[i].chunk_size;      // taille taille chunk
  1223.                 back[i].r.totalsize=-1;                 // total inconnu
  1224.                 back[i].r.out=NULL;
  1225.                 back[i].r.is_file=0;
  1226.                 //
  1227.                 retour_fread=http_xfread1(&(back[i].r),0);
  1228.                 // modifier et restaurer
  1229.                 back[i].chunk_adr=back[i].r.adr;        // adresse
  1230.                 back[i].chunk_size=back[i].r.size;      // taille taille chunk
  1231.                 bcopy((char*) &r, (char*) &(back[i].r), sizeof(htsblk));    // restaurer vΘritable r
  1232.               }
  1233.               else if (back[i].is_chunk) {         // attention chunk, limiter taille α lire
  1234. #if CHUNKDEBUG==1
  1235.                 printf("read %d bytes\n",(int)min(back[i].r.totalsize-back[i].r.size,TAILLE_BUFFER));
  1236. #endif
  1237.                 retour_fread=http_xfread1(&(back[i].r),(int)min(back[i].r.totalsize-back[i].r.size,TAILLE_BUFFER));
  1238.               } else
  1239.                 retour_fread=http_fread1(&(back[i].r));
  1240.             } else
  1241.               retour_fread=-1;                    // interruption ou annulation interne (peut ne pas Ωtre une erreur)
  1242.             
  1243.             // Si rΘception chunk, tester si on est pas α la fin!
  1244.             if (back[i].status==1) {
  1245.               if (back[i].is_chunk) {     // attendre prochain chunk
  1246.                 if (back[i].r.size==back[i].r.totalsize) {      // fin chunk!
  1247.                   //printf("chunk end at %d\n",back[i].r.size);
  1248.                   back[i].status=98;  // prochain chunk
  1249.                   if (back[i].chunk_adr!=NULL) { freet(back[i].chunk_adr); back[i].chunk_adr=NULL; } back[i].chunk_size=0;
  1250.                   retour_fread=0;       // pas d'erreur
  1251. #if CHUNKDEBUG==1
  1252.                   printf("waiting for next chunk header (soc %d)..\n",back[i].r.soc);
  1253. #endif
  1254.                 }
  1255.               }
  1256.             }
  1257.                           
  1258.             if (retour_fread==-1) {    // erreur rΘception
  1259.               back[i].status=0;    // terminΘ
  1260.               if (back[i].r.soc!=INVALID_SOCKET) {
  1261. #if HTS_DEBUG_CLOSESOCK
  1262.                 DEBUG_W("back_wait(4): deletehttp\n");
  1263. #endif
  1264.                 deletehttp(&back[i].r);
  1265.               }
  1266.               back[i].r.soc=INVALID_SOCKET;
  1267. #if CHUNKDEBUG==1
  1268.               if (back[i].is_chunk)
  1269.                 printf("must be the last chunk for %s (connection closed) - %d/%d\n",back[i].url_fil,back[i].r.size,back[i].r.totalsize);
  1270. #endif
  1271.               //if ((back[i].r.statuscode==-1) && (strnotempty(back[i].r.msg)==0)) {
  1272.               if ((back[i].r.statuscode<0) && (strnotempty(back[i].r.msg)==0)) {
  1273. #if HDEBUG
  1274.                 printf("error interruped: %s\n",back[i].r.adr);
  1275. #endif        
  1276.                 if (back[i].r.size>0)
  1277.                   strcat(back[i].r.msg,"Interrupted transfer");
  1278.                 else
  1279.                   strcat(back[i].r.msg,"No data (connection closed)");
  1280.                 back[i].r.statuscode=-4;
  1281.               }
  1282.  
  1283.               if (back[i].r.totalsize>0) {    // tester totalsize
  1284.               //if ((back[i].r.totalsize>0) && (back[i].status==99)) {    // tester totalsize
  1285.                 if (back[i].r.totalsize!=back[i].r.size) {  // pas la mΩme!
  1286.                   if (!opt->tolerant) {
  1287.                     //#if HTS_CL_IS_FATAL
  1288.                     if (back[i].r.adr) freet(back[i].r.adr); back[i].r.adr=NULL;
  1289.                     if (back[i].r.size<back[i].r.totalsize)
  1290.                       back[i].r.statuscode=-4;        // recatch
  1291.                     sprintf(back[i].r.msg,"Incorrect length ("LLintP" Bytes, "LLintP" expected)",back[i].r.size,back[i].r.totalsize);
  1292.                   } else {
  1293.                     //#else
  1294.                     // Un warning suffira..
  1295.                     if (cache->errlog!=NULL) {
  1296.                       fspc(cache->errlog,"warning"); fprintf(cache->errlog,"Incorrect length ("LLintP"!="LLintP" expected) for %s%s"LF,back[i].r.size,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1297.                     }
  1298.                     //#endif
  1299.                   }
  1300.                 }
  1301.               }
  1302. #if BDEBUG==1
  1303.               printf("transfer ok\n");
  1304. #endif
  1305.             } else {    // pas d'erreur de rΘception
  1306.               if (back[i].timeout>0) {    // refresh timeout si besoin est
  1307.                 back[i].timeout_refresh=time_local();
  1308.               }
  1309.  
  1310.               // Traitement des en tΩtes chunks ou en tΩtes
  1311.               if (back[i].status==98) {        // rΘception taille chunk en hexa (  aprΦs les en tΩtes, peut ne pas
  1312.                 if (back[i].chunk_size>=2) {
  1313.                   int chunk_size=-1;
  1314.                   // Ωtre prΘsent)
  1315.                   if (back[i].chunk_adr[back[i].chunk_size-1]==10) {    // LF, fin ligne chunk
  1316.                     char chunk_data[64];
  1317.                     if (back[i].chunk_size<32) {      // pas trop gros
  1318.                       back[i].chunk_adr[ back[i].chunk_size-1]='\0';    // octet nul 
  1319.                       strcpy(chunk_data,"");    // hex number
  1320.                       strcat(chunk_data,back[i].chunk_adr);
  1321. #if CHUNKDEBUG==1
  1322.                       printf("chunk received and read: %s\n",chunk_data);
  1323. #endif
  1324.                       if (back[i].r.totalsize<0)
  1325.                         back[i].r.totalsize=0;        // initialiser α 0
  1326.                       if (sscanf(chunk_data,"%x",&chunk_size) == 1) {
  1327.                         back[i].r.totalsize+=chunk_size;    // noter taille
  1328.                         back[i].r.adr=(char*) realloct(back[i].r.adr,(INTsys) back[i].r.totalsize + 1);
  1329.                         if (!back[i].r.adr) {
  1330.                           if (cache->errlog!=NULL) {
  1331.                             fprintf(cache->errlog,"Error: Not enough memory ("LLintP") for %s%s"LF,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1332.                           }
  1333.                         }
  1334. #if CHUNKDEBUG==1
  1335.                         printf("chunk length: %d - next total "LLintP":\n",chunk_size,back[i].r.totalsize);
  1336. #endif
  1337.                       } else                                
  1338.                         if (cache->errlog!=NULL) {
  1339.                           fprintf(cache->errlog,"Warning: Illegal chunk (%s) for %s%s"LF,back[i].chunk_adr,back[i].url_adr,back[i].url_fil);
  1340.                         }
  1341.                     } else {                                  
  1342.                       if (cache->errlog!=NULL) {
  1343.                         fprintf(cache->errlog,"Warning: Chunk too big ("LLintP") for %s%s"LF,back[i].chunk_size,back[i].url_adr,back[i].url_fil);
  1344.                       }
  1345.                     }
  1346.                     
  1347.                     // ok, continuer sur le body
  1348.                     
  1349.                     // si chunk non nul continuer (ou commencer)
  1350.                     if (chunk_size>0) {
  1351.                       back[i].status=1;     // continuer body    
  1352. #if CHUNKDEBUG==1
  1353.                       printf("waiting for body (chunk)\n");
  1354. #endif
  1355.                     } else {                // chunk nul, c'est la fin
  1356. #if CHUNKDEBUG==1
  1357.                       printf("chunk end, total: %d\n",back[i].r.size);
  1358. #endif
  1359.                       back[i].status=0;     // fin    
  1360.                       if (back[i].r.soc!=INVALID_SOCKET) {
  1361. #if HTS_DEBUG_CLOSESOCK
  1362.                         DEBUG_W("back_wait(5): deletehttp\n");
  1363. #endif
  1364.                         deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1365.  
  1366.                         /* Tester totalsize en fin de chunk */
  1367.                         if ((back[i].r.totalsize>0)) {    // tester totalsize
  1368.                           if (back[i].r.totalsize!=back[i].r.size) {  // pas la mΩme!
  1369. #if HTS_CL_IS_FATAL
  1370.                             if (back[i].r.adr) { freet(back[i].r.adr); back[i].r.adr=NULL; }
  1371.                             back[i].r.statuscode=-1;
  1372.                             strcpy(back[i].r.msg,"Incorrect length");
  1373. #else
  1374.                             // Un warning suffira..
  1375.                             if (cache->errlog!=NULL) {
  1376.                               fspc(cache->errlog,"warning"); fprintf(cache->errlog,"Incorrect length ("LLintP"!="LLintP" expected) for %s%s"LF,back[i].r.size,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1377.                             }
  1378. #endif
  1379.                           }
  1380.                         }
  1381.                         
  1382.                       
  1383.                       }
  1384.                     }
  1385.  
  1386.                     // effacer buffer (chunk en tete)
  1387.                     if (back[i].chunk_adr!=NULL) {
  1388.                       freet(back[i].chunk_adr);
  1389.                       back[i].chunk_adr=NULL;
  1390.                       back[i].chunk_size=0;
  1391.                     }
  1392.                   
  1393.                   } // chunk LF?
  1394.                 }  // taille buffer chunk>2
  1395.                 //
  1396.               } else if (back[i].status==99) {        // en tΩtes (avant le chunk si il est prΘsent)
  1397.                 //
  1398.                 if (back[i].r.size>=2) {
  1399.                   if ((back[i].r.adr[back[i].r.size-1]==10) && (back[i].r.adr[back[i].r.size-2]==10)) {
  1400.                     char rcvd[2048];
  1401.                     int ptr=0;
  1402.                     
  1403. #if BDEBUG==1
  1404.                     printf("..ok, header received\n");
  1405. #endif
  1406.                     
  1407.                     // ----------------------------------------
  1408.                     // traiter en-tΩte!
  1409.                     // status-line α rΘcupΘrer
  1410.                     ptr+=binput(back[i].r.adr+ptr,rcvd,2000);
  1411.                     if (strnotempty(rcvd)==0)
  1412.                       ptr+=binput(back[i].r.adr+ptr,rcvd,2000);    // "certains serveurs buggΘs envoient un \n au dΘbut" (RFC)
  1413.                     
  1414.                     // traiter status-line
  1415.                     treatfirstline(&back[i].r,rcvd);
  1416.                     
  1417. #if HDEBUG
  1418.                     printf("(Buffer) Status-Code=%d\n",back[i].r.statuscode);
  1419. #endif
  1420.                     if (_DEBUG_HEAD) {
  1421.                       if (ioinfo) {
  1422.                         fprintf(ioinfo,"\r\nresponse for %s%s:\r\n",back[i].url_adr,back[i].url_fil);
  1423.                         fprintf(ioinfo,"(Buffer) Status-Code=%d\r\n",back[i].r.statuscode);
  1424.                         fflush(ioinfo);
  1425.                       }                    // en-tΩte
  1426.                     }
  1427.                       
  1428.                     // header // ** !attention! HTTP/0.9 non supportΘ
  1429.                     do {
  1430.                       ptr+=binput(back[i].r.adr+ptr,rcvd,2000);          
  1431. #if HDEBUG
  1432.                       printf("(buffer)>%s\n",rcvd);      
  1433. #endif
  1434.                       if (_DEBUG_HEAD) {
  1435.                         if (ioinfo) {
  1436.                           fprintf(ioinfo,"(buffer)>%s\r\n",rcvd);      
  1437.                           fflush(ioinfo);
  1438.                         }
  1439.                       }
  1440.  
  1441.                       if (strnotempty(rcvd))
  1442.                         treathead(opt->cookie,back[i].url_adr,back[i].url_fil,&back[i].r,rcvd);  // traiter
  1443.                       
  1444.                       // parfois les serveurs buggΘs renvoient un content-range avec un 200
  1445.                       if (back[i].r.statuscode==200)  // 'OK'
  1446.                         if (strfield(rcvd,"content-range:"))  // Avec un content-range: relisez les RFC..
  1447.                           back[i].r.statuscode=206;    // FORCER A 206 !!!!!
  1448.                         
  1449.                     } while(strnotempty(rcvd));
  1450.                     // ----------------------------------------                    
  1451.                     
  1452.                     // libΘrer mΘmoire  -- aprΦs! --
  1453.                     if (back[i].r.adr!=NULL) { freet(back[i].r.adr); back[i].r.adr=NULL; }
  1454.  
  1455.                     
  1456.  
  1457.  
  1458.                     /* 
  1459.                        Status code and header-response hacks
  1460.                     */
  1461.                     
  1462.                     // Check response : 203 == 200
  1463.                     if (back[i].r.statuscode==203) {  // 'Non-Authoritative Information'
  1464.                       back[i].r.statuscode=200;       // forcer "OK"
  1465.                     }
  1466.                     
  1467.  
  1468.                     // Various hacks to limit re-transfers when updating a mirror
  1469.                     if (opt->sizehack) {
  1470.                       // We already have the file
  1471.                       // and ask the remote server for an update
  1472.                       // Some servers, especially dynamic pages severs, always
  1473.                       // answer that the page has been modified since last visit
  1474.                       // And answer with a 200 (OK) response, and the same page
  1475.                       // If the size is the same, and the option has been set, we assume
  1476.                       // that the file is identical - and therefore let's break the connection
  1477.                       if (back[i].is_update) {          // mise α jour
  1478.                         if (back[i].r.statuscode==200) {  // 'OK'
  1479.                           htsblk r = cache_read(opt,cache,back[i].url_adr,back[i].url_fil,NULL);    // lire entrΘe cache
  1480.                           if (r.statuscode == 200) {  // OK pas d'erreur cache
  1481.                             LLint len1,len2;
  1482.                             len1=r.totalsize;
  1483.                             len2=back[i].r.totalsize;
  1484.                             if (r.size>0)
  1485.                               len1=r.size;
  1486.                             if (len1>0) {
  1487.                               if (len1 == len2) {             // tailles identiques
  1488.                                 back[i].r.statuscode=304;     // forcer NOT MODIFIED
  1489.                                 deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1490.                                 if ((opt->debug>1) && (opt->log!=NULL)) {
  1491.                                   fspc(opt->log,"debug"); fprintf(opt->log,"File seems complete (same size), breaking connection: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1492.                                 }
  1493.                               }
  1494.                             }
  1495.                           } else {
  1496.                             if (opt->errlog!=NULL) {
  1497.                               fspc(opt->errlog,"warning"); fprintf(opt->errlog,"File seems complete (same size), but there was a cache read error: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1498.                             }
  1499.                           }
  1500.                         }
  1501.                       }
  1502.                     }
  1503.                     /* 
  1504.                     End of status code and header-response hacks
  1505.                     */
  1506.                     
  1507.                     
  1508.                     
  1509.                     /* Interdiction taille par le wizard? */
  1510.                     if (back[i].r.soc!=INVALID_SOCKET) {
  1511.                       if (!back_checksize(opt,&back[i],1)) {
  1512.                         back[i].status=0;  // FINI
  1513.                         deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1514.                         if (!back[i].testmode)
  1515.                           strcpy(back[i].r.msg,"File too big");
  1516.                         else
  1517.                           strcpy(back[i].r.msg,"Test: File too big");
  1518.                       }
  1519.                     }
  1520.                     
  1521.                     /* sinon, continuer */
  1522.                     /* if (back[i].r.soc!=INVALID_SOCKET) {   // ok rΘcupΘrer body? */
  1523.                     // head: terminΘ
  1524.                     if (back[i].head_request) {
  1525.                       if ((opt->debug>1) && (opt->log!=NULL)) {
  1526.                         fspc(opt->log,"debug"); fprintf(opt->log,"Tested file: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1527.                       }
  1528. #if HTS_DEBUG_CLOSESOCK
  1529.                       DEBUG_W("back_wait(head request): deletehttp\n");
  1530. #endif
  1531.                       // Couper connexion
  1532.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1533.                       back[i].status=0;  // terminΘ
  1534.                     }
  1535.                     // traiter une Θventuelle erreur 304 (cache α jour utilisable)
  1536.                     else if (back[i].r.statuscode==304) {  // document α jour dans le cache
  1537.                       // lire dans le cache
  1538.                       // ** NOTE: pas de vΘrif de la taille ici!!
  1539. #if HTS_DEBUG_CLOSESOCK
  1540.                       DEBUG_W("back_wait(file is not modified): deletehttp\n");
  1541. #endif
  1542.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1543.                       back[i].r=cache_read(opt,cache,back[i].url_adr,back[i].url_fil,back[i].url_sav);
  1544.                       if (!back[i].r.location)
  1545.                         back[i].r.location=back[i].location_buffer;
  1546.                       else {        /* recopier */
  1547.                         strcpy(back[i].location_buffer,back[i].r.location);
  1548.                         back[i].r.location=back[i].location_buffer;
  1549.                       }
  1550.                       if (back[i].r.statuscode!=-1) { // pas d'erreur de lecture
  1551.                         back[i].status=0;         // OK prΩt
  1552.                         back[i].r.notmodified=1;  // NON modifiΘ!
  1553.                         if ((opt->debug>0) && (opt->log!=NULL)) {
  1554.                           fspc(opt->log,"debug"); fprintf(opt->log,"File loaded after test from cache: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1555.                         }
  1556. #if DEBUGCA
  1557.                         printf("..document α jour aprΦs requΦte: %s%s\n",back[i].url_adr,back[i].url_fil);
  1558. #endif
  1559.                         
  1560.                         //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode);
  1561.                       } else {  // erreur
  1562.                         back[i].status=0;  // terminΘ
  1563.                         //printf("erreur cache\n");
  1564.                         
  1565.                       } 
  1566.                       
  1567.                     } else if ((back[i].r.statuscode==301)
  1568.                       || (back[i].r.statuscode==302)
  1569.                       || (back[i].r.statuscode==303)
  1570.                       || (back[i].r.statuscode==307)
  1571.                       || (back[i].r.statuscode==412)
  1572.                       || (back[i].r.statuscode==416)
  1573.                       ) {   // Ne pas prendre le html, erreurs connues et gΘrΘes
  1574. #if HTS_DEBUG_CLOSESOCK
  1575.                       DEBUG_W("back_wait(301,302,303,307,412,416..): deletehttp\n");
  1576. #endif
  1577.                       // Couper connexion
  1578.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1579.                       back[i].status=0;  // terminΘ
  1580.                       
  1581.                     } else {    // il faut aller le chercher
  1582.                       
  1583.                       // effacer buffer (requΦte)
  1584.                       if (back[i].r.adr!=NULL) {
  1585.                         freet(back[i].r.adr);
  1586.                         back[i].r.adr=NULL;
  1587.                       }
  1588.                       back[i].r.size=0;                                 
  1589.                       
  1590.                       // traiter 206 (partial content)
  1591.                       // xxc SI CHUNK VERIFIER QUE CA MARCHE??
  1592.                       if (back[i].r.statuscode==206) {  // on nous envoie un morceau (la fin) coz une partie sur disque!
  1593.                         LLint sz=fsize(back[i].url_sav);
  1594. #if HDEBUG
  1595.                         printf("partial content: "LLintP" on disk..\n",(LLint)sz);
  1596. #endif
  1597.                         if (sz>=0) {
  1598.                           if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1599.                             if (opt->getmode&2) {    // on peut ecrire des non html  **sinon ben euhh sera interceptΘ plus loin, donc rap sur ce qui va sortir**
  1600.                               filenote(back[i].url_sav,NULL);    // noter fichier comme connu
  1601.                               back[i].r.out=fopen(fconv(back[i].url_sav),"ab");  // append
  1602.                               if (back[i].r.out) {
  1603.                                 back[i].r.is_write=1;    // Θcrire
  1604.                                 back[i].r.size=sz;    // dΘja Θcrit
  1605.                                 back[i].r.statuscode=200;  // Forcer 'OK'
  1606.                                 if (back[i].r.totalsize>0)
  1607.                                   back[i].r.totalsize+=sz;    // plus en fait
  1608.                                 fseek(back[i].r.out,0,SEEK_END);  // α la fin
  1609. #if HDEBUG
  1610.                                 printf("continue interrupted file\n");
  1611. #endif
  1612.                               } else {    // On est dans la m**
  1613.                                 back[i].status=0;  // terminΘ (voir plus loin)
  1614.                                 strcpy(back[i].r.msg,"Can not open partial file");
  1615.                               }
  1616.                             }
  1617.                           } else {    // mΘmoire
  1618.                             FILE* fp=fopen(fconv(back[i].url_sav),"rb");
  1619.                             if (fp) {
  1620.                               LLint alloc_mem=sz + 1;
  1621.                               if (back[i].r.totalsize>0)
  1622.                                 alloc_mem+=back[i].r.totalsize;            // AJOUTER RESTANT!
  1623.                               if ( (back[i].r.adr=(char*) malloct((INTsys) alloc_mem)) ) {
  1624.                                 back[i].r.size=sz;
  1625.                                 if (back[i].r.totalsize>0)
  1626.                                   back[i].r.totalsize+=sz;    // plus en fait
  1627.                                 if (((int) fread(back[i].r.adr,1,(INTsys)sz,fp)) != sz) {
  1628.                                   back[i].status=0;  // terminΘ (voir plus loin)
  1629.                                   strcpy(back[i].r.msg,"Can not read partial file");
  1630.                                 } else {
  1631.                                   back[i].r.statuscode=200;  // Forcer 'OK'
  1632. #if HDEBUG
  1633.                                   printf("continue in mem interrupted file\n");
  1634. #endif
  1635.                                 }
  1636.                               } else {
  1637.                                 back[i].status=0;  // terminΘ (voir plus loin)
  1638.                                 strcpy(back[i].r.msg,"No memory for partial file");
  1639.                               }
  1640.                             } else {  // Argh.. 
  1641.                               back[i].status=0;  // terminΘ (voir plus loin)
  1642.                               strcpy(back[i].r.msg,"Can not open partial file");
  1643.                             }
  1644.                           }
  1645.                         } else {    // Non trouvΘ??
  1646.                           back[i].status=0;  // terminΘ (voir plus loin)
  1647.                           strcpy(back[i].r.msg,"Can not find partial file");
  1648.                         }
  1649.                         // Erreur?
  1650.                         if (back[i].status==0) {
  1651.                           if (back[i].r.soc!=INVALID_SOCKET) {
  1652. #if HTS_DEBUG_CLOSESOCK
  1653.                             DEBUG_W("back_wait(206 solve problems): deletehttp\n");
  1654. #endif
  1655.                             deletehttp(&back[i].r);
  1656.                           }
  1657.                           back[i].r.soc=INVALID_SOCKET;
  1658.                           //back[i].r.statuscode=206;  ????????
  1659.                           back[i].r.statuscode=-5;
  1660.                           if (strnotempty(back[i].r.msg))
  1661.                             strcpy(back[i].r.msg,"Error attempting to solve status 206 (partial file)");
  1662.                         }
  1663.                       }
  1664.                       
  1665.                       if (back[i].status!=0) {  // non terminΘ (erreur)
  1666.                         if (!back[i].testmode) {    // fichier normal
  1667.                           
  1668.                           if (!back[i].r.is_chunk) {    // pas de chunk
  1669.                             //if (back[i].r.http11!=2) {    // pas de chunk
  1670.                             back[i].is_chunk=0;
  1671.                             back[i].status=1;     // start body
  1672.                           } else {
  1673. #if CHUNKDEBUG==1
  1674.                             printf("chunk encoding detected %s..\n",back[i].url_fil);
  1675. #endif
  1676.                             back[i].is_chunk=1;
  1677.                             back[i].chunk_adr=NULL;
  1678.                             back[i].chunk_size=0;
  1679.                             back[i].status=98;    // start body wait chunk
  1680.                           }
  1681.                           if (back[i].rateout>0) {
  1682.                             back[i].rateout_time=time_local();  // refresh pour transfer rate
  1683.                           }
  1684. #if HDEBUG
  1685.                           printf("(buffer) start body!\n");
  1686. #endif
  1687.                         } else {     // mode test, ne pas passer en 1!!
  1688.                           back[i].status=0;    // READY
  1689. #if HTS_DEBUG_CLOSESOCK
  1690.                           DEBUG_W("back_wait(test ok): deletehttp\n");
  1691. #endif
  1692.                           deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1693.                           if (back[i].r.statuscode==200) {
  1694.                             strcpy(back[i].r.msg,"Test: OK");
  1695.                             back[i].r.statuscode=-10;    // test rΘussi
  1696.                           }
  1697.                           else {    // test a ΘchouΘ, on ne change rien sauf que l'erreur est α titre indicatif
  1698.                             char tempo[1000];
  1699.                             strcpy(tempo,back[i].r.msg);
  1700.                             strcpy(back[i].r.msg,"Test: ");
  1701.                             strcat(back[i].r.msg,tempo);
  1702.                           }
  1703.                           
  1704.                         }
  1705.                       }
  1706.                       
  1707.                       } 
  1708.                       
  1709.                       /*}*/
  1710.                       
  1711.                   }  // si LF
  1712.                 }  // r.size>2
  1713.               }  // si == 99
  1714.               
  1715.             } // si pas d'erreurs
  1716. #if BDEBUG==1
  1717.             printf("bytes overall: %d\n",back[i].r.size);
  1718. #endif
  1719.           }  // donnΘes dispo
  1720.           
  1721.           // en cas d'erreur cl, supprimer Θventuel fichier sur disque
  1722. #if HTS_REMOVE_BAD_FILES
  1723.           if (back[i].status<0) {
  1724.             if (!back[i].testmode) {    // pas en test
  1725.               remove(back[i].url_sav);    // Θliminer fichier (endommagΘ)
  1726.               //printf("&& %s\n",back[i].url_sav);
  1727.             }
  1728.           }
  1729. #endif
  1730.  
  1731.           /* funny log for commandline users */
  1732.           if (!opt->quiet) {  // petite animation
  1733.             if (opt->verbosedisplay) {
  1734.               if (back[i].status==0) {
  1735.                 if (back[i].r.statuscode==200)
  1736.                   printf("* %s%s ("LLintP" bytes) - OK\33[K\r",back[i].url_adr,back[i].url_fil,back[i].r.size);
  1737.                 else
  1738.                   printf("* %s%s ("LLintP" bytes) - %d\33[K\r",back[i].url_adr,back[i].url_fil,back[i].r.size,back[i].r.statuscode);
  1739.                 fflush(stdout);
  1740.               }
  1741.             }
  1742.           }
  1743.           
  1744.  
  1745.       } // status>0
  1746.     }  // for
  1747.     
  1748.     // vΘrifier timeouts
  1749.     if (gestion_timeout) {
  1750.       double act;
  1751.       act=time_local();    // temps en secondes
  1752.       for(i=0;i<back_max;i++) {
  1753.         if (back[i].status>0) {  // rΘception/connexion/..
  1754.           if (back[i].timeout>0) {
  1755.             //printf("time check %d\n",((int) (act-back[i].timeout_refresh))-back[i].timeout);
  1756.             if (((int) (act-back[i].timeout_refresh))>=back[i].timeout) {
  1757.               if (back[i].r.soc!=INVALID_SOCKET) {
  1758. #if HTS_DEBUG_CLOSESOCK
  1759.                 DEBUG_W("back_wait(timeout): deletehttp\n");
  1760. #endif
  1761.                 deletehttp(&back[i].r);
  1762.               }
  1763.               back[i].r.soc=INVALID_SOCKET;
  1764.               back[i].r.statuscode=-2;
  1765.               if (back[i].status==100)
  1766.                 strcpy(back[i].r.msg,"Connect Time Out");
  1767.               else if (back[i].status==101)
  1768.                 strcpy(back[i].r.msg,"DNS Time Out");
  1769.               else
  1770.                 strcpy(back[i].r.msg,"Receive Time Out");
  1771.               back[i].status=0;  // terminΘ
  1772.             } else if ((back[i].rateout>0) && (back[i].status<99)) {
  1773.               if (((int) (act-back[i].rateout_time))>=HTS_WATCHRATE) {   // checker au bout de 15s
  1774.                 if ( (int) ((back[i].r.size)/(act-back[i].rateout_time)) < back[i].rateout ) {  // trop lent
  1775.                   back[i].status=0;  // terminΘ
  1776.                   if (back[i].r.soc!=INVALID_SOCKET) {
  1777. #if HTS_DEBUG_CLOSESOCK
  1778.                     DEBUG_W("back_wait(rateout): deletehttp\n");
  1779. #endif
  1780.                     deletehttp(&back[i].r);
  1781.                   }
  1782.                   back[i].r.soc=INVALID_SOCKET;
  1783.                   back[i].r.statuscode=-3;
  1784.                   strcpy(back[i].r.msg,"Transfer Rate Too Low");
  1785.                 }
  1786.               }
  1787.             }
  1788.           }
  1789.         }
  1790.       }
  1791.     }
  1792.     max_loop--;
  1793. #if HTS_ANALYSTE==2
  1794.     max_loop_chk++;
  1795. #endif
  1796.   } while((busy) && (max_loop>0));
  1797. #if HTS_ANALYSTE==2
  1798.   if (!busy) {
  1799.     if (max_loop_chk>=1) {
  1800.       Sleep(10);    // un tite pause pour Θviter les lag..
  1801.     }
  1802.   }
  1803. #endif
  1804. }
  1805.  
  1806. int back_checksize(httrackp* opt,lien_back* eback,int check_only_totalsize) {
  1807.   LLint size_to_test;
  1808.   if (check_only_totalsize)
  1809.     size_to_test=eback->r.totalsize;
  1810.   else
  1811.     size_to_test=max(eback->r.totalsize,eback->r.size);
  1812.   if (size_to_test>=0) {
  1813.     
  1814.     /* Interdiction taille par le wizard? */
  1815.     if (hts_testlinksize(opt,eback->url_adr,eback->url_fil,(eback->r.totalsize+1023)/1024)==-1) {
  1816.       return 0;     /* interdit */
  1817.     }                     
  1818.     
  1819.     /* vΘrifier taille classique (heml et non html) */
  1820.     if ((istoobig(size_to_test,eback->maxfile_html,eback->maxfile_nonhtml,eback->r.contenttype))) {
  1821.       return 0;     /* interdit */
  1822.     }
  1823.   }
  1824.   return 1;
  1825. }
  1826.  
  1827.  
  1828. // octets transfΘrΘs + add
  1829. LLint back_transfered(LLint nb,lien_back* back,int back_max) {
  1830.   int i;
  1831.   // ajouter octets en instance
  1832.   for(i=0;i<back_max;i++)
  1833.     if ((back[i].status>0) && (back[i].status<99))
  1834.       nb+=back[i].r.size;
  1835.   return nb;      
  1836. }
  1837.  
  1838. // infos backing
  1839. // j: 1 afficher sockets 2 afficher autres 3 tout afficher
  1840. void back_info(lien_back* back,int i,int j,FILE* fp) {
  1841.   if (back[i].status>=0) {
  1842.     char s[256]; 
  1843.          s[0]='\0';
  1844.     back_infostr(back,i,j,s);
  1845.     strcat(s,LF);
  1846.     fprintf(fp,"%s",s);
  1847.   }
  1848. }
  1849.  
  1850. // infos backing
  1851. // j: 1 afficher sockets 2 afficher autres 3 tout afficher
  1852. void back_infostr(lien_back* back,int i,int j,char* s) {
  1853.   if (back[i].status>=0) {
  1854.     int aff=0;
  1855.     if (j & 1) {
  1856.       if (back[i].status==100) {
  1857.         strcat(s,"CONNECT ");
  1858.       } else if (back[i].status==99) {
  1859.         strcat(s,"INFOS ");
  1860.         aff=1;
  1861.       } else if (back[i].status==98) {
  1862.         strcat(s,"INFOSC");             // infos chunk
  1863.         aff=1;
  1864.       }
  1865.       else if (back[i].status>0) {
  1866. #if HTS_ANALYSTE==2
  1867.         strcat(s,"WAIT ");
  1868. #else
  1869.         strcat(s,"RECEIVE "); 
  1870. #endif
  1871.         aff=1; 
  1872.       }
  1873.     } 
  1874.     if (j & 2) {
  1875.       if (back[i].status==0) {
  1876.         switch (back[i].r.statuscode) {
  1877.         case 200:
  1878.           strcat(s,"READY ");
  1879.           aff=1;
  1880.           break;
  1881. #if HTS_ANALYSTE==2
  1882.         default:
  1883.           strcat(s,"ERROR ");
  1884.           break;
  1885. #else
  1886.         case -1:
  1887.           strcat(s,"ERROR ");
  1888.           aff=1;
  1889.           break;
  1890.         case -2:
  1891.           strcat(s,"TIMEOUT ");
  1892.           aff=1;
  1893.           break;
  1894.         case -3:
  1895.           strcat(s,"TOOSLOW ");
  1896.           aff=1;
  1897.           break;
  1898.         case 400:
  1899.           strcat(s,"BADREQUEST ");
  1900.           aff=1;
  1901.           break;
  1902.         case 401: case 403:
  1903.           strcat(s,"FORBIDDEN ");
  1904.           aff=1;
  1905.           break;
  1906.         case 404:
  1907.           strcat(s,"NOT FOUND ");
  1908.           aff=1;
  1909.           break;
  1910.         case 500:
  1911.           strcat(s,"SERVERROR ");
  1912.           aff=1;
  1913.           break;
  1914.         default:
  1915.           {
  1916.             char s2[256];
  1917.             sprintf(s2,"ERROR(%d)",back[i].r.statuscode);
  1918.             strcat(s,s2);
  1919.           }
  1920.           aff=1;
  1921. #endif
  1922.         }
  1923.       }
  1924.     }
  1925.     
  1926.     if (aff) {
  1927.       {
  1928.         char s2[256];
  1929.         sprintf(s2,"\"%s",back[i].url_adr); strcat(s,s2);
  1930.         
  1931.         if (back[i].url_fil[0]!='/') strcat(s,"/");
  1932.         sprintf(s2,"%s\" ",back[i].url_fil); strcat(s,s2);
  1933.         sprintf(s,LLintP" "LLintP" ",back[i].r.size,back[i].r.totalsize); strcat(s,s2);
  1934.       }
  1935.     }
  1936.   }
  1937. }
  1938.  
  1939. // -- backing --
  1940.  
  1941. #undef test_flush
  1942.