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

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche, Yann Philippot
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. This project has been developed by Xavier Roche and Yann Philippot,
  29. from the company Serianet at Caen, France (http://www.serianet.com)
  30.  
  31. Please visit our Website: http://www.httrack.com
  32. */
  33.  
  34.  
  35. /* ------------------------------------------------------------ */
  36. /* File: Main source                                            */
  37. /* Author: Xavier Roche                                         */
  38. /* ------------------------------------------------------------ */
  39.  
  40. #include "httrack.h"
  41.  
  42. /* specific definitions */
  43. #include "htsbase.h"
  44. #include "htsnet.h"
  45. #include "htsbauth.h"
  46. #include "htsmd5.h"
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #include <time.h>
  51. #include <fcntl.h>
  52. #include <ctype.h>
  53. /* END specific definitions */
  54.  
  55.  
  56. /* HTML parsing */
  57. #if HTS_ANALYSTE==2
  58. char _hts_errmsg[1100]="";
  59. int _hts_in_html_parsing=0;
  60. int _hts_in_html_done=0;  // % done
  61. int _hts_in_html_poll=0;  // parsing
  62. int _hts_setpause=0;
  63. httrackp* _hts_setopt=NULL;
  64. char** _hts_addurl=NULL;
  65. //
  66. int _hts_cancel=0;
  67. #endif
  68.  
  69.  
  70.  
  71. char* structcheck_buff=NULL;
  72. int exit_xh;          /* quick exit (fatal error or interrupt) */
  73.  
  74. /* debug */
  75. #if DEBUG_SHOWTYPES
  76. char REG[32768]="\n";
  77. #endif
  78. #if NSDEBUG
  79. int nsocDEBUG=0;
  80. #endif
  81.  
  82. //
  83. #define _CLRSCR printf("\33[m\33[2J");
  84. #define _GOTOXY(X,Y) printf("\33[" X ";" Y "f");
  85.  
  86. #if DEBUG_CHECKINT
  87.  #define _CHECKINT_FAIL(a) printf("\n%s\n",a); fflush(stdout); exit(1);
  88.  #define _CHECKINT(obj_ptr,message) \
  89.    if (obj_ptr) {\
  90.      if (( * ((char*) (obj_ptr)) != 0) || ( * ((char*) (((char*) (obj_ptr)) + sizeof(*(obj_ptr))-1)) != 0)) {\
  91.        char msg[1100];\
  92.        if (( * ((char*) (obj_ptr)) != 0) && ( * ((char*) (((char*) (obj_ptr)) + sizeof(*(obj_ptr))-1)) != 0))\
  93.          sprintf(msg,"* PANIC: Integrity error (structure crushed)  in: %s",message);\
  94.        else if ( * ((char*) (obj_ptr)) != 0)\
  95.          sprintf(msg,"* PANIC: Integrity error (start of structure) in: %s",message);\
  96.        else\
  97.          sprintf(msg,"* PANIC: Integrity error (end of structure)   in: %s",message);\
  98.        _CHECKINT_FAIL(msg);\
  99.      }\
  100.    } else {\
  101.      char msg[1100];\
  102.      sprintf(msg,"* PANIC: NULL pointer in: %s",message);\
  103.      _CHECKINT_FAIL(msg);\
  104.    }
  105. #endif
  106.  
  107. #if DEBUG_HASH
  108.   // longest hash chain?
  109.   int longest_hash[3]={0,0,0},hashnumber=0;
  110. #endif
  111.  
  112. // demande d'interaction avec le shell
  113. #if HTS_ANALYSTE==2
  114. char HTbuff[1100];
  115. #endif
  116.  
  117.  
  118.  
  119. // DΘbut de httpmirror, routines annexes
  120.  
  121. // version 1 pour httpmirror
  122. // flusher si on doit lire peu α peu le fichier
  123. #define test_flush if (opt.flush) { fflush(opt.log); fflush(opt.errlog); }
  124.  
  125. // pour allΘger la syntaxe, des raccourcis sont crΘΘs
  126. #define urladr   (liens[ptr]->adr)
  127. #define urlfil   (liens[ptr]->fil)
  128. #define savename (liens[ptr]->sav)
  129. #define level    (liens[ptr]->prio)
  130. #define new_stat_bytes HTS_TOTAL_RECV
  131.  
  132. // au cas o∙ nous devons quitter rapidement xhttpmirror (plus de mΘmoire, etc)
  133. // note: partir de liens_max.. vers 0.. sinon erreur de violation de mΘmoire: les liens suivants
  134. // ne sont plus α nous.. agh! [dur celui-lα]
  135. #if HTS_ANALYSTE
  136.  #define HTMLCHECK_UNINIT hts_htmlcheck_end();
  137. #else
  138. #define HTMLCHECK_UNINIT 
  139. #endif
  140.  
  141. #define XH_extuninit { \
  142.   int i; \
  143.   HTMLCHECK_UNINIT \
  144.   if (liens!=NULL) { \
  145.   for(i=lien_max-1;i>0;i--) { \
  146.   if (liens[i]) { \
  147.   if (liens[i]->firstblock==1) { \
  148.   freet(liens[i]); \
  149.   liens[i]=NULL; \
  150.   } \
  151.   } \
  152.   } \
  153.   liens=NULL; \
  154.   } \
  155.   if (filters[0]) { \
  156.   freet(filters[0]); filters[0]=NULL; \
  157.   } \
  158.   if (back) { \
  159.   int i; \
  160.   for(i=0;i<back_max;i++) { \
  161.   back_delete(back,i); \
  162.   } \
  163.   freet(back); back=NULL;  \
  164.   } \
  165.   checkrobots_free(&robots);\
  166.   if (cache.use) { freet(cache.use); cache.use=NULL; } \
  167.   if (cache.dat) { fclose(cache.dat); cache.dat=NULL; }  \
  168.   if (cache.ndx) { fclose(cache.ndx); cache.ndx=NULL; } \
  169.   if (cache.olddat) { fclose(cache.olddat); cache.olddat=NULL; } \
  170.   if (cache.lst) { fclose(cache.lst); cache.lst=NULL; } \
  171.   if (opt.log) fflush(opt.log); \
  172.   if (opt.errlog) fflush(opt.errlog);\
  173.   if (makestat_fp) { fclose(makestat_fp); makestat_fp=NULL; } \
  174.   if (maketrack_fp){ fclose(maketrack_fp); maketrack_fp=NULL; } \
  175.   if (opt.accept_cookie) cookie_save(opt.cookie,fconcat(opt.path_log,"cookies.txt")); \
  176.   if (makeindex_fp) { fclose(makeindex_fp); makeindex_fp=NULL; } \
  177.   if (cache_hash) { inthash_del(cache_hash,cache_hash_size); cache_hash=NULL; } \
  178. }
  179. #define XH_uninit XH_extuninit if (r.adr) { freet(r.adr); r.adr=NULL; } 
  180.  
  181. // Enregistrement d'un lien:
  182. // on calcule la taille nΘcessaire: taille des 3 chaεnes α stocker (taille forcΘe paire, plus 2 octets de sΘcuritΘ)
  183. // puis on vΘrifie qu'on a assez de marge dans le buffer - sinon on en rΘalloue un autre
  184. // enfin on Θcrit α l'adresse courante du buffer, qu'on incrΘmente. on dΘcrΘmente la taille dispo d'autant ensuite
  185. // codebase: si non nul et si .class stockee on le note pour chemin primaire pour classes
  186. // FA,FS: former_adr et former_fil, lien original
  187. #define HTS_ALIGN 4
  188. #if HTS_HASH
  189. #define liens_record_sav_len(A) 
  190. #else
  191. #define liens_record_sav_len(A) (A)->sav_len=strlen((A)->sav)
  192. #endif
  193.  
  194. #define liens_record(A,F,S,FA,FF) { \
  195. int notecode=0; \
  196. int adr_len=strlen(A),fil_len=strlen(F),sav_len=strlen(S),cod_len=0,former_adr_len=strlen(FA),former_fil_len=strlen(FF); \
  197. if (former_adr_len>0) {\
  198. former_adr_len=(former_adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  199. former_fil_len=(former_fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  200. } else former_adr_len=former_fil_len=0;\
  201. if (strlen(F)>6) if (strnotempty(codebase)) if (strfield(F+strlen(F)-6,".class")) { notecode=1; \
  202. cod_len=strlen(codebase); cod_len=(cod_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; } \
  203. adr_len=(adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; fil_len=(fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; sav_len=(sav_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  204. if ((int) lien_size < (int) (adr_len+fil_len+sav_len+cod_len+former_adr_len+former_fil_len+sizeof(lien_url))) { \
  205. lien_buffer=(char*) ((void*) calloct(add_tab_alloc,1)); \
  206. lien_size=add_tab_alloc; \
  207. if (lien_buffer!=NULL) { \
  208. liens[lien_tot]=(lien_url*) (void*) lien_buffer; lien_buffer+=sizeof(lien_url); lien_size-=sizeof(lien_url); \
  209. liens[lien_tot]->firstblock=1; \
  210. } \
  211. } else { \
  212. liens[lien_tot]=(lien_url*) (void*) lien_buffer; lien_buffer+=sizeof(lien_url); lien_size-=sizeof(lien_url); \
  213. liens[lien_tot]->firstblock=0; \
  214. } \
  215. if (liens[lien_tot]!=NULL) { \
  216. liens[lien_tot]->adr=lien_buffer; lien_buffer+=adr_len; lien_size-=adr_len; \
  217. liens[lien_tot]->fil=lien_buffer; lien_buffer+=fil_len; lien_size-=fil_len; \
  218. liens[lien_tot]->sav=lien_buffer; lien_buffer+=sav_len; lien_size-=sav_len; \
  219. liens[lien_tot]->cod=NULL; \
  220. if (notecode) { liens[lien_tot]->cod=lien_buffer; lien_buffer+=cod_len; lien_size-=cod_len; strcpy(liens[lien_tot]->cod,codebase); } \
  221. if (former_adr_len>0) {\
  222. liens[lien_tot]->former_adr=lien_buffer; lien_buffer+=former_adr_len; lien_size-=former_adr_len; \
  223. liens[lien_tot]->former_fil=lien_buffer; lien_buffer+=former_fil_len; lien_size-=former_fil_len; \
  224. strcpy(liens[lien_tot]->former_adr,FA); \
  225. strcpy(liens[lien_tot]->former_fil,FF); \
  226. }\
  227. strcpy(liens[lien_tot]->adr,A); \
  228. strcpy(liens[lien_tot]->fil,F); \
  229. strcpy(liens[lien_tot]->sav,S); \
  230. liens_record_sav_len(liens[lien_tot]); \
  231. hash_write(&hash,lien_tot);  \
  232. } \
  233. }
  234.  
  235. /* - abandonnΘ (simplifie) -
  236. // Ajouter α un lien EXISTANT deux champs former_adr et former_fil pour indiquer le nom d'un fichier avant un "move"
  237. // NOTE: si un alloc est fait ici il n'y aura pas de freet() α la fin, tant pis (firstbloc)
  238. #define liens_add_former(index,A,F) { \
  239. int adr_len=strlen(A),fil_len=strlen(F); \
  240. adr_len=(adr_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; fil_len=(fil_len/HTS_ALIGN)*HTS_ALIGN+HTS_ALIGN+4; \
  241. if ((int) lien_size < (int) (adr_len+fil_len)) { \
  242. lien_buffer=(char*) calloct(add_tab_alloc,1); \
  243. lien_size=add_tab_alloc; \
  244. } \
  245. if (lien_buffer!=NULL) { \
  246. if (liens[lien_tot]!=NULL) { \
  247. liens[lien_tot]->former_adr=lien_buffer; lien_buffer+=adr_len; lien_size-=adr_len; \
  248. liens[lien_tot]->former_fil=lien_buffer; lien_buffer+=fil_len; lien_size-=fil_len; \
  249. strcpy(liens[lien_tot]->former_adr,A); \
  250. strcpy(liens[lien_tot]->former_fil,F); \
  251. } \
  252. } \
  253. }
  254. */
  255.  
  256. #if 0
  257. #define HT_ADD_ADR { \
  258.   fwrite(lastsaved,1,((int) adr)- ((int) lastsaved),fp); \
  259.   lastsaved=adr; }
  260. #define HT_ADD(A) fwrite(A,1,(int) strlen(A),fp);
  261. #define HT_ADD_START
  262. #define HT_ADD_END if (fp) { fclose(fp); fp=NULL; }
  263. #define HT_ADD_FOP { \
  264.   fp=filecreate(savename); \
  265.   if (fp==NULL) { \
  266.   if (opt.errlog) { \
  267.   fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to create %s for %s%s"LF,savename,urladr,urlfil); \
  268.   test_flush; \
  269.   } \
  270.   freet(r.adr); r.adr=NULL; \
  271.   error=1; \
  272.   } \
  273.   }
  274. #else
  275. // version optimisΘe, qui permet de ne pas toucher aux html non modifiΘs (update)
  276. #define HT_ADD_CHK(A) if (((int) A+ht_len+1)>ht_size) { \
  277.   ht_size=A+ht_len+8192; \
  278.   ht_buff=(char*) realloct(ht_buff,ht_size); \
  279.   if (ht_buff==NULL) { \
  280.   printf("PANIC! : Not enough memory [%d]\n",__LINE__); \
  281.   XH_uninit; \
  282.   } \
  283.   } \
  284.   ht_len+=A;
  285. #define HT_ADD_ADR { int i,j=ht_len; HT_ADD_CHK(((int) adr)- ((int) lastsaved)) \
  286.   for(i=0;i<((int) adr)- ((int) lastsaved);i++) \
  287.   ht_buff[j+i]=lastsaved[i]; \
  288.   ht_buff[j+((int) adr)- ((int) lastsaved)]='\0'; \
  289.   lastsaved=adr; }
  290. #define HT_ADD(A) { HT_ADD_CHK(strlen(A)) strcat(ht_buff,A); }
  291. #define HT_ADD_START \
  292.   int ht_size=(int)(r.size*5)/4+8192; \
  293.   int ht_len=0; \
  294.   char* ht_buff=NULL; \
  295.   if ((opt.getmode & 1) && (ptr>0)) { \
  296.   ht_buff=(char*) malloct(ht_size); \
  297.   if (ht_buff==NULL) { \
  298.   printf("PANIC! : Not enough memory [%d]\n",__LINE__); \
  299.   XH_uninit; \
  300.   } \
  301.   ht_buff[0]='\0'; \
  302.   }
  303. #define HT_ADD_END { \
  304.   int ok=0;\
  305.   if (ht_buff) { \
  306.   int file_len=(int) strlen(ht_buff);\
  307.   char digest[32+2];\
  308.   digest[0]='\0';\
  309.   domd5mem(ht_buff,file_len,digest,1,0);\
  310.   if (fsize(antislash(savename))==file_len) { \
  311.   int mlen;\
  312.   char* mbuff;\
  313.   cache_readdata(&cache,"//[HTML-MD5]//",savename,&mbuff,&mlen);\
  314.   if (mlen) mbuff[mlen]='\0';\
  315.   if ((mlen == 32) && (strcmp(((mbuff!=NULL)?mbuff:""),digest)==0)) {\
  316.   ok=1;\
  317.   if ( (opt.debug>1) && (opt.log!=NULL) ) {\
  318.   fspc(opt.log,"debug"); fprintf(opt.log,"File not re-written (md5): %s"LF,savename);\
  319.   test_flush;\
  320.   }\
  321.   } else {\
  322.   FILE* fp2; \
  323.   int i=0; \
  324.   fp2=fopen(fconv(savename),"rb"); \
  325.   if (fp2) { \
  326.   ok=1; \
  327.   while((!feof(fp2)) && (ok)) { int c=fgetc(fp2); if (c!=EOF) { if ((char) c!=(char) ht_buff[i++]) ok=0; } } \
  328.   fclose(fp2); \
  329.   } \
  330.   } \
  331.   }\
  332.   if (!ok) { \
  333.   fp=filecreate(savename); \
  334.   if (fp) { \
  335.   if ((int)fwrite(ht_buff,1,file_len,fp) != file_len) { \
  336.   if (opt.errlog) {   \
  337.   fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unable to write HTML file %s"LF,savename);\
  338.   test_flush;\
  339.   }\
  340.   }\
  341.   fclose(fp); fp=NULL; \
  342.   if (strnotempty(r.lastmodified)) \
  343.   set_filetime_rfc822(savename,r.lastmodified); \
  344.   usercommand(0,NULL,antislash(savename)); \
  345.   } \
  346.   } else filenote(savename,NULL); \
  347.   if (cache.ndx)\
  348.   cache_writedata(cache.ndx,cache.dat,"//[HTML-MD5]//",savename,digest,(int)strlen(digest));\
  349.   } \
  350.   freet(ht_buff); ht_buff=NULL; \
  351.   }
  352. #define HT_ADD_FOP 
  353. #endif
  354.  
  355. // libΘrer filters[0] pour insΘrer un ΘlΘment dans filters[0]
  356. #define HT_INSERT_FILTERS0 {\
  357.   int i;\
  358.   if (filptr>0) {\
  359.     for(i=filptr-1;i>=0;i--) {\
  360.       strcpy(filters[i+1],filters[i]);\
  361.     }\
  362.   }\
  363.   strcpy(filters[0],"");\
  364.   filptr++;\
  365.   filptr=minimum(filptr,filter_max);\
  366. }
  367.  
  368. // DΘbut de httpmirror, robot
  369. // url1 peut Ωtre multiple
  370. int httpmirror(char* url1,int level1,httrackp opt) {
  371.   char* primary=NULL;          // premiΦre page, contenant les liens α scanner
  372.   int lien_tot=0;              // nombre de liens pour le moment
  373.   lien_url** liens=NULL;       // les pointeurs sur les liens
  374.   hash_struct hash;            // systΦme de hachage, accΘlΦre la recherche dans les liens
  375.   t_cookie cookie;             // gestion des cookies
  376.   int lien_max=0;
  377.   int lien_size=0;        // octets restants dans buffer liens dispo
  378.   char* lien_buffer=NULL; // buffer liens actuel
  379.   int add_tab_alloc=256000;    // +256K de liens α chaque fois
  380.   //char* tab_alloc=NULL;
  381.   int ptr;             // pointeur actuel sur les liens
  382.   //
  383.   int numero_passe=0;  // deux passes pour html puis images
  384.   int back_max=0;      // fichiers qui peuvent Ωtre en local
  385.   lien_back* back=NULL; // backing en local
  386.   htsblk r;            // retour de certaines fonctions
  387.   double lastime=0;    // pour affichage infos de tmp en tmp
  388.   // pour les stats, nombre de fichiers & octets Θcrits
  389.   int stat_files=0;    // nombre de fichiers Θcrits
  390.   int stat_updated_files=0;    // nombre de fichiers mis α jour
  391.   LLint stat_bytes=0;          // octets Θcrits sur disque
  392.   LLint stat_fragment=0;  // pour la fragmentation
  393.   double stat_timestart;  // dΘpart
  394.   //
  395.   double last_info_shell=0;
  396.   int info_shell=0;
  397.   // note: α amΘliorer // **
  398.   char* filters[usd_max];
  399.   int filter_max=0;
  400.   int filptr=0;
  401.   //
  402.   int makeindex_done=0;  // lorsque l'index sera fait
  403.   FILE* makeindex_fp=NULL;
  404.   // statistiques (mode #Z)
  405.   FILE* makestat_fp=NULL;    // fichier de stats taux transfert
  406.   FILE* maketrack_fp=NULL;   // idem pour le tracking
  407.   double makestat_time=0;    // attente (secondes)
  408.   LLint makestat_total=0;    // repΦre du nombre d'octets transfΘrΘs depuis denriΦre stat
  409.   int makestat_lnk=0;        // idem, pour le nombre de liens
  410.   //
  411.   char codebase[HTS_URLMAXSIZE*2];  // base pour applet java
  412.   char base[HTS_URLMAXSIZE*2];      // base pour les autres fichiers
  413.   //
  414.   cache_back cache;
  415.   robots_wizard robots;    // gestion robots.txt
  416.   hash_chain** cache_hash=NULL;
  417.   int cache_hash_size=0;
  418.   //
  419.   codebase[0]='\0'; base[0]='\0';
  420.   //
  421.   cookie.auth.next=NULL;
  422.   cookie.auth.auth[0]=cookie.auth.prefix[0]='\0';
  423.   //
  424.  
  425.   // noter heure actuelle de dΘpart en secondes
  426.   stat_timestart=time_local();
  427.   /* reset stats */
  428.   new_stat_bytes=0;
  429.   if (opt.aff_progress)
  430.     lastime=stat_timestart;
  431.   if (opt.shell) {
  432.     last_info_shell=stat_timestart;
  433.   }
  434.   if ((opt.makestat) || (opt.maketrack)){
  435.     makestat_time=stat_timestart;
  436.   }
  437.  
  438.   // initialiser cookie
  439.   if (opt.accept_cookie) {
  440.     opt.cookie=&cookie;
  441.     cookie.max_len=30000;       // max len
  442.     strcpy(cookie.data,"");
  443.     // Charger cookies.txt par dΘfaut ou cookies.txt du miroir
  444.     if (fexist(fconcat(opt.path_log,"cookies.txt")))
  445.       cookie_load(opt.cookie,opt.path_log,"cookies.txt");
  446.     else if (fexist("cookies.txt"))
  447.       cookie_load(opt.cookie,"","cookies.txt");
  448.   } else
  449.     opt.cookie=NULL;
  450.  
  451.   // initialiser exit_xh
  452.   exit_xh=0;          // sortir prΘmaturΘment (var globale)
  453.  
  454.   // initialiser usercommand
  455.   usercommand(opt.sys_com_exec,opt.sys_com,"");
  456.   
  457.   // effacer bloc cache
  458.   bzero((char *)&cache, sizeof(cache_back));
  459.   cache.type=opt.cache;  // cache?
  460.   cache.errlog=opt.errlog;  // err log?
  461.   cache.ptr_ant=cache.ptr_last=0;   // pointeur pour anticiper
  462.  
  463.   // initialiser hash cache
  464.   if (!cache_hash_size) 
  465.     cache_hash_size=HTS_HASH_SIZE;
  466.   cache_hash=(hash_chain**)calloc(cache_hash_size,sizeof(hash_chain*));
  467.   if (cache_hash==NULL) {
  468.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  469.     filters[0]=NULL; back_max=0;    // uniquement a cause du warning de XH_extuninit
  470.     XH_extuninit;
  471.     return 0;
  472.   }
  473.   inthash_init(cache_hash,cache_hash_size);
  474.   cache.hash=(void**)cache_hash;      /* copy backcache hash */
  475.   cache.hash_size=cache_hash_size;
  476.  
  477.   // initialiser cache DNS
  478.   _hts_lockdns(-999);
  479.  
  480.   // robots.txt
  481.   strcpy(robots.adr,"!");    // dummy
  482.   robots.token[0]='\0';
  483.   robots.next=NULL;          // suivant
  484.   
  485.   // effacer filters
  486.   filter_max=maximum(opt.maxfilter,32);
  487.   filters[0]=(char*) malloct((filter_max+1)*(HTS_URLMAXSIZE*2));
  488.   if (filters[0]==NULL) {
  489.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  490.     back_max=0;    // uniquement a cause du warning de XH_extuninit
  491.     XH_extuninit;
  492.     return 0;
  493.   } else {
  494.     int i;
  495.     for(i=0;i<=filter_max;i++) {    // PLUS UN (sΘcuritΘ)
  496.       filters[i]=filters[0]+i*(HTS_URLMAXSIZE*2);
  497.       filters[i][0]='\0';
  498.     }
  499.   }
  500.   opt.filters.filptr=&filptr;
  501.   opt.filters.filter_max=&filter_max;
  502.   opt.filters.filters=filters;
  503.  
  504.   // tableau de pointeurs sur les liens
  505.   lien_max=maximum(opt.maxlink,32);
  506.   liens=(lien_url**) malloct(lien_max*sizeof(lien_url*));   // tableau de pointeurs sur les liens
  507.   if (liens==NULL) {
  508.     printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  509.     //XH_uninit;
  510.     return 0;
  511.   } else {
  512.     int i;
  513.     for(i=0;i<lien_max;i++) {
  514.       liens[i]=NULL;     
  515.     }
  516.   }
  517.   // initialiser ptr et lien_tot
  518.   ptr=0;
  519.   lien_tot=0;
  520. #if HTS_HASH
  521.   // initialiser hachage
  522.   {
  523.     int i;
  524.     for(i=0;i<HTS_HASH_SIZE;i++)
  525.       hash.hash[0][i]=hash.hash[1][i]=hash.hash[2][i] = -1;    // pas d'entrΘes
  526.     hash.liens = liens;
  527.     hash.max_lien=0;
  528.   }
  529. #endif
  530.  
  531.   
  532.   // copier adresse(s) dans liste des adresses
  533.   {
  534.     char *a=url1;
  535.     int primary_len=8192;
  536.     if (strnotempty(opt.filelist)) {
  537.       primary_len+=max(0,fsize(opt.filelist)*2);
  538.     }
  539.     primary_len+=strlen(url1)*2;
  540.  
  541.     // crΘation de la premiΦre page, qui contient les liens de base α scanner
  542.     // c'est plus propre et plus logique que d'entrer α la main les liens dans la pile
  543.     // on bΘnΘficie ainsi des vΘrifications et des tests du robot pour les liens "primaires"
  544.     primary=(char*) malloct(primary_len); 
  545.     if (primary) {
  546.       primary[0]='\0';
  547.     } else {
  548.       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  549.       back_max=0;    // uniquement a cause du warning de XH_extuninit
  550.       XH_extuninit;
  551.       return 0;
  552.     }
  553.     
  554.     while(*a) {
  555.       int i;
  556.       int joker=0;
  557.  
  558.       // vΘrifier qu'il n'y a pas de * dans l'url
  559.       if (*a=='+')
  560.         joker=1;
  561.       else if (*a=='-')
  562.         joker=1;
  563.       /* NON, certaines URL ont des * (!)
  564.       else {
  565.         int i=0;
  566.         while((a[i]!=0) && (a[i]!=' ')) if (a[i++]=='*') joker=1;
  567.       }
  568.       */
  569.       
  570.       if (joker) {    // joker ou filters
  571.         //char* p;
  572.         char tempo[HTS_URLMAXSIZE*2];
  573.         int type; int plus=0;
  574.  
  575.         // noter joker (dans b)
  576.         if (*a=='+') {  // champ +
  577.           type=1; plus=1; a++;
  578.         } else if (*a=='-') {  // champ forbidden[]
  579.           type=0; a++;
  580.         } else {  // champ + avec joker sans doute
  581.           type=1;
  582.         }
  583.  
  584.         // recopier prochaine chaine (+ ou -)
  585.         i=0;
  586.         while((*a!=0) && (*a!=' ')) { tempo[i++]=*a; a++; }  
  587.         tempo[i++]='\0';
  588.         while(*a==' ') { a++; }
  589.  
  590.         // sauter les + sans rien aprΦs..
  591.         if (strnotempty(tempo)) {
  592.           if ((plus==0) && (type==1)) {  // implicite: *www.edf.fr par exemple
  593.             if (tempo[strlen(tempo)-1]!='*') {
  594.               strcat(tempo,"*");  // ajouter un *
  595.             }
  596.           }
  597.           if (type)
  598.             strcpy(filters[filptr],"+");
  599.           else
  600.             strcpy(filters[filptr],"-");
  601.           if (strncmp(tempo,"http://",7)==0)
  602.             strcat(filters[filptr],tempo+7);        // ignorer http://
  603.           else
  604.             strcat(filters[filptr],tempo);
  605.           filptr++;          
  606.         }
  607.         
  608.       } else {    // adresse normale
  609.         char url[HTS_URLMAXSIZE*2];
  610.         // prochaine adresse
  611.         i=0;
  612.         while((*a!=0) && (*a!=' ')) { url[i++]=*a; a++; }  
  613.         while(*a==' ') { a++; }
  614.         url[i++]='\0';
  615.  
  616.         strcat(primary,"<PRIMARY=\"");
  617.         if (strstr(url,":/")==NULL)
  618.           strcat(primary,"http://");
  619.         strcat(primary,url);
  620.         strcat(primary,"\">\n");
  621.       }
  622.     }  // while
  623.  
  624.     /* intΘgrer liste de fichiers */
  625.     if (strnotempty(opt.filelist)) {
  626.       FILE* fp=fopen(opt.filelist,"rb");
  627.       if (fp) {
  628.         int n=0;
  629.         char line[512];
  630.         while(!feof(fp)) {
  631.           linput(fp,line,500);
  632.           if (strnotempty(line)) {
  633.             n++;
  634.             strcat(primary,"<PRIMARY=\"");
  635.             if (strstr(line,":/")==NULL)
  636.               strcat(primary,"http://");
  637.             strcat(primary,line);
  638.             strcat(primary,"\">\n");
  639.           }
  640.         }
  641.         fclose(fp);
  642.         if (opt.log!=NULL) {
  643.           fspc(opt.log,"info"); fprintf(opt.log,"%d links added from %s"LF,n,opt.filelist); test_flush;
  644.         }
  645.       } else {
  646.         if (opt.errlog!=NULL) {
  647.           fspc(opt.errlog,"error"); fprintf(opt.errlog,"Could not include URL list: %s"LF,opt.filelist); test_flush;
  648.         }
  649.       }
  650.     }
  651.  
  652.  
  653.     // lien primaire
  654.     liens_record("primary","/primary","primary.html","","");
  655.     if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  656.       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  657.       if (opt.errlog) {
  658.         fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  659.         test_flush;
  660.       }
  661.       back_max=0;    // uniquement a cause du warning de XH_extuninit
  662.       XH_extuninit;    // dΘsallocation mΘmoire & buffers
  663.       return 0;
  664.     }    
  665.     liens[lien_tot]->testmode=0;          // pas mode test
  666.     liens[lien_tot]->link_import=0;       // pas mode import
  667.     liens[lien_tot]->prio=level1+1;       // lien de prioritΘ maximale
  668.     liens[lien_tot]->pass2=0;             // 1Φre passe
  669.     liens[lien_tot]->retry=opt.retry;     // lien de prioritΘ maximale
  670.     liens[lien_tot]->premier=lien_tot;    // premier lien, objet-pΦre=objet              
  671.     liens[lien_tot]->precedent=lien_tot;  // lien prΘcΘdent
  672.     lien_tot++;  
  673.  
  674.     // Initialiser cache
  675.     cache_init(&cache,&opt);
  676.   }
  677.   
  678. #if BDEBUG==3
  679.   {
  680.     int i;
  681.     for(i=0;i<lien_tot;i++) {
  682.       printf("%d>%s%s as %s\n",i,liens[i]->adr,liens[i]->fil,liens[i]->sav);
  683.     }
  684.     for(i=0;i<filptr;i++) {
  685.       printf("%d>filters=%s\n",i,filters[i]);
  686.     }
  687.   }
  688. #endif
  689.    
  690.   // backing
  691.   //soc_max=opt.maxsoc;
  692.   if (opt.maxsoc>0) {
  693. #if BDEBUG==2
  694.     _CLRSCR;
  695. #endif
  696.     // Nombre de fichiers HTML pouvant Ωtre prΘsents en mΘmoire de maniΦre simultannΘe
  697.     // On prΘvoit large: les fichiers HTML ne prennent que peu de place en mΘmoire, et les
  698.     // fichiers non html sont sauvΘs en direct sur disque.
  699.     // --> 256 entrΘes + 32 entrΘes par socket en supplΘment
  700.     back_max=opt.maxsoc*32+256;
  701.     //back_max=opt.maxsoc*8+32;
  702.     back=(lien_back*) calloct((back_max+1),sizeof(lien_back));
  703.     if (back==NULL) {
  704.       if (opt.errlog)
  705.         fprintf(opt.errlog,"Not enough memory, can not allocate %d bytes"LF,(opt.maxsoc+1)*sizeof(lien_back));
  706.       return 0;
  707.     } else {    // copier buffer-location & effacer
  708.       int i;
  709.       for(i=0;i<back_max;i++){
  710.         back[i].r.location=back[i].location_buffer;
  711.         back[i].status=-1;
  712.         back[i].r.soc=INVALID_SOCKET;
  713.       }
  714.     }
  715.   }
  716.  
  717.  
  718.   // flush
  719.   test_flush;
  720.  
  721.   // statistiques
  722.   if (opt.makestat) {
  723.     makestat_fp=fopen(fconcat(opt.path_log,"hts-stats.txt"),"wb");
  724.     if (makestat_fp != NULL) {
  725.       fprintf(makestat_fp,"HTTrack statistics report, every minutes"LF LF);
  726.     }
  727.   }
  728.  
  729.   // tracking -- dΘbuggage
  730.   if (opt.maketrack) {
  731.     maketrack_fp=fopen(fconcat(opt.path_log,"hts-track.txt"),"wb");
  732.     if (maketrack_fp != NULL) {
  733.       fprintf(maketrack_fp,"HTTrack tracking report, every minutes"LF LF);
  734.     }
  735.   }
  736.  
  737.   // on n'a pas de liens!! (exemple: httrack www.* impossible sans dΘpart..)
  738.   if (lien_tot<=0) {
  739.     if (opt.errlog) {
  740.       fprintf(opt.errlog,"Error! You MUST specify at least one complete URL, and not only wildcards!"LF);
  741.     }
  742.   }
  743.  
  744.  
  745.   // attendre une certaine heure..
  746.   if (opt.waittime>0) {
  747.     int rollover=0;
  748.     int ok=0;
  749.     {
  750.       double tl=0;
  751.       time_t tt;
  752.       struct tm* A;
  753.       tt=time(NULL);
  754.       A=localtime(&tt);
  755.       tl+=A->tm_sec;
  756.       tl+=A->tm_min*60;
  757.       tl+=A->tm_hour*60*60;
  758.       if (tl>opt.waittime)  // attendre minuit
  759.         rollover=1;
  760.     }
  761.  
  762.     // attendre..
  763.     do {
  764.       double tl=0;
  765.       time_t tt;
  766.       struct tm* A;
  767.       tt=time(NULL);
  768.       A=localtime(&tt);
  769.       tl+=A->tm_sec;
  770.       tl+=A->tm_min*60;
  771.       tl+=A->tm_hour*60*60;
  772.  
  773.       if (rollover) {
  774.         if (tl<=opt.waittime)
  775.           rollover=0;  // attendre heure
  776.       } else {
  777.         if (tl>opt.waittime)
  778.           ok=1;  // ok!
  779.       }
  780.       
  781. #if HTS_ANALYSTE
  782.       {  
  783.         int r;
  784.         if (rollover)
  785.           r=hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,(int) (opt.waittime-tl+24*3600),-1,-1,-1,-1);
  786.         else
  787.           r=hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,(int) (opt.waittime-tl),-1,-1,-1,-1);
  788.         if (!r) {
  789.           exit_xh=1;  // exit requested
  790.           ok=1;          
  791.         } else
  792.           Sleep(100);
  793.       }
  794. #endif
  795.     } while(!ok);    
  796.     
  797.     // note: recopie de plus haut
  798.     // noter heure actuelle de dΘpart en secondes
  799.     stat_timestart=time_local();
  800.     if (opt.aff_progress)
  801.       lastime=stat_timestart;
  802.     if (opt.shell) {
  803.       last_info_shell=stat_timestart;
  804.     }
  805.     if ((opt.makestat) || (opt.maketrack)){
  806.       makestat_time=stat_timestart;
  807.     }
  808.  
  809.  
  810.   }  
  811. #if HTS_ANALYSTE
  812.   if (!hts_htmlcheck_loop(back,back_max,0,0,lien_tot,0,0,0,-1,-1,-1,-1)) {
  813.     XH_extuninit;
  814.     return 1;
  815.   }
  816.   Sleep(100);
  817.   if (!hts_htmlcheck_start()) {
  818.     XH_extuninit;
  819.     return 1;
  820.   }
  821. #endif
  822.   
  823.  
  824.   // ------------------------------------------------------------
  825.  
  826.   // ------------------------------------------------------------
  827.   // Boucle gΘnΘrale de parcours des liens
  828.   // ------------------------------------------------------------
  829.   do {
  830.     int error=0;          // si error alors sauter
  831.     int store_errpage=0;  // c'est une erreur mais on enregistre le html
  832.     char loc[HTS_URLMAXSIZE*2];    // adresse de relocation
  833.  
  834.     // Ici on charge le fichier (html, gif..) en mΘmoire
  835.     // Les HTMLs sont traitΘs (si leur prioritΘ est suffisante)
  836.  
  837.     // effacer r
  838.     bzero((char *)&r, sizeof(htsblk)); r.soc=INVALID_SOCKET;
  839.     r.location=loc;    // en cas d'erreur 3xx (moved)
  840.     // recopier proxy
  841.     bcopy((char*) &opt.proxy,(char*) &(r.req.proxy), sizeof(opt.proxy));
  842.     // et user-agent
  843.     strcpy(r.req.user_agent,opt.user_agent);
  844.     r.req.user_agent_send=opt.user_agent_send;
  845.  
  846.     if (!error) {
  847.       
  848.       if (liens[ptr]) {
  849.         while (  ( ((urladr != NULL)?(urladr):(" "))[0]=='!') ||
  850.                  ( ((urlfil != NULL)?(urlfil):(" "))[0]=='\0') ) {  // sauter si lien annulΘ (ou fil vide)
  851.           ptr++;
  852.         }
  853.       }
  854.       if (liens[ptr]) {    // on a qq chose α rΘcupΘrer?
  855.  
  856.         if ( (opt.debug>1) && (opt.log!=NULL) ) {
  857.           fspc(opt.log,"debug"); fprintf(opt.log,"Wait get: %s%s"LF,urladr,urlfil);
  858.           test_flush;
  859. #if DEBUG_ROBOTS
  860.           if (strcmp(urlfil,"/robots.txt") == 0) {
  861.             printf("robots.txt detected\n");
  862.           }
  863. #endif
  864.         }    
  865.         // ------------------------------------------------------------
  866.         // DEBUT --RECUPERATION LIEN---
  867.         if (ptr==0) {              // premier lien α parcourir: lien primaire construit avant
  868.           r.adr=primary; primary=NULL;
  869.           r.statuscode=200;
  870.           r.size=strlen(r.adr);
  871.           r.soc=INVALID_SOCKET;
  872.           strcpy(r.contenttype,"text/html");
  873.         /*} else if (opt.maxsoc<=0) {   // fichiers 1 α 1 en attente (pas de backing)
  874.           // charger le fichier en mΘmoire tout bΩtement
  875.           r=xhttpget(urladr,urlfil);
  876.           //
  877.         */
  878.         } else {    // backing, multiples sockets
  879.           //
  880.           int b;
  881.           int n;
  882.           
  883. #if BDEBUG==1
  884.           printf("\nBack test..\n");
  885. #endif
  886.  
  887.           if (opt.fragment>0) {
  888.             if ((stat_bytes-stat_fragment) > opt.fragment) {
  889.               while (back_nsoc(back,back_max)>0) {                  // attendre fin des transferts
  890.                 back_wait(back,back_max,&opt,&cache,stat_timestart);
  891.                 Sleep(100);
  892.               }
  893.               // On dΘsalloue le buffer d'enregistrement des chemins crΘΘe, au cas o∙ pendant la pause
  894.               // l'utilisateur ferait un rm -r aprΦs avoir effectuΘ un tar
  895.               if (structcheck_buff) {
  896.                 freet(structcheck_buff);
  897.                 structcheck_buff=NULL;
  898.               }
  899.               {
  900.                 FILE* fp = fopen(fconcat(opt.path_log,"hts-paused.lock"),"wb");
  901.                 if (fp) {
  902.                   fspc(fp,"info");  // dater
  903.                   fprintf(fp,"Pause\nHTTrack is paused after retreiving "LLintP" bytes\nDelete this file to continue the mirror...\n\n",stat_bytes);
  904.                   fclose(fp);
  905.                 }
  906.               }
  907.               stat_fragment=stat_bytes;
  908.               while (fexist(fconcat(opt.path_log,"hts-paused.lock"))) {
  909.                 //back_wait(back,back_max,&opt,&cache,stat_timestart);   inutile!! (plus de sockets actives)
  910.                 Sleep(1000);
  911.               }
  912.             }
  913.           }
  914.  
  915. #if HTS_ANALYSTE==2
  916.           // changement dans les prΘfΘrences
  917.           if (_hts_setopt) {
  918.             copy_htsopt(_hts_setopt,&opt);    // copier au besoin
  919.             _hts_setopt=NULL;                 // effacer callback
  920.           }
  921.           if (_hts_addurl) {
  922.             char add_adr[HTS_URLMAXSIZE*2];
  923.             char add_fil[HTS_URLMAXSIZE*2];
  924.             while(*_hts_addurl) {
  925.               char add_url[HTS_URLMAXSIZE*2];
  926.               add_adr[0]=add_fil[0]=add_url[0]='\0';
  927.               if (strstr(*_hts_addurl,"://")==NULL)
  928.                 strcpy(add_url,"http://");          // ajouter http://
  929.               strcat(add_url,*_hts_addurl);
  930.               if (ident_url(add_url,add_adr,add_fil)>=0) {
  931.                 // ----Ajout----
  932.                 // noter NOUVEAU lien
  933.                 char add_sav[HTS_URLMAXSIZE*2];
  934.                 // calculer lien et Θventuellement modifier addresse/fichier
  935.                 if (url_savename(add_adr,add_fil,add_sav,NULL,NULL,NULL,NULL,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe)!=-1) { 
  936.                   if (hash_read(&hash,add_sav,"",0)<0) {      // n'existe pas dΘja
  937.                     // enregistrer lien (MACRO)
  938.                     liens_record(add_adr,add_fil,add_sav,"","");
  939.                     if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  940.                       liens[lien_tot]->testmode=0;          // mode test?
  941.                       liens[lien_tot]->link_import=0;       // mode normal
  942.                       liens[lien_tot]->prio=level1;
  943.                       liens[lien_tot]->pass2=max(0,numero_passe);
  944.                       liens[lien_tot]->retry=opt.retry;
  945.                       liens[lien_tot]->premier=lien_tot;
  946.                       liens[lien_tot]->precedent=lien_tot;
  947.                       lien_tot++;
  948.                       //
  949.                       if ((opt.debug>0) && (opt.log!=NULL)) {
  950.                         fspc(opt.log,"info"); fprintf(opt.log,"Link added by user: %s%s"LF,add_adr,add_fil); test_flush;
  951.                       }
  952.                       //
  953.                     } else {  // oups erreur, plus de mΘmoire!!
  954.                       printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  955.                       if (opt.errlog) {
  956.                         fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  957.                         test_flush;
  958.                       }
  959.                       //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  960.                       XH_uninit;    // dΘsallocation mΘmoire & buffers
  961.                       return 0;
  962.                     }
  963.                   } else {
  964.                     if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  965.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Existing link %s not added after user request"LF,add_adr,add_fil);
  966.                       test_flush;
  967.                     }
  968.                   }
  969.                   
  970.                 }
  971.               } else {
  972.                 if (opt.errlog) {
  973.                   fspc(opt.errlog,"error");
  974.                   fprintf(opt.errlog,"Error during URL decoding for %s%s"LF,add_url);
  975.                   test_flush;
  976.                 }
  977.               }
  978.               // ----Fin Ajout----
  979.               _hts_addurl++;                  // suivante
  980.             }
  981.             _hts_addurl=NULL;           // libΘrer _hts_addurl
  982.           }
  983.           // si une pause a ΘtΘ demandΘe
  984.           if (_hts_setpause) {
  985.             // index du lien actuel
  986.             int b=back_index(back,back_max,urladr,urlfil,savename);
  987.             if (b<0) b=0;    // forcer pour les stats
  988.             while(_hts_setpause) {    // on fait la pause..
  989.               LLint nb;
  990.               back_wait(back,back_max,&opt,&cache,stat_timestart);
  991.               nb=back_transfered(stat_bytes,back,back_max);
  992.               if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,nb,new_stat_bytes,(int) (time_local()-stat_timestart),back_nsoc(back,back_max),stat_files,stat_updated_files,fspc(NULL,"error") )) {
  993.                 if (opt.errlog) {
  994.                   fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  995.                   test_flush;
  996.                 }
  997.                 exit_xh=1;  // exit requested
  998.                 XH_uninit;
  999.                 return 0;
  1000.               }
  1001.               if (back_nsoc(back,back_max)==0)
  1002.                 Sleep(250);  // tite pause
  1003.             }
  1004.           }
  1005. #endif
  1006.           
  1007.           // si le fichier n'est pas en backing, le mettre..
  1008.           if (!back_exist(back,back_max,urladr,urlfil,savename)) {
  1009. #if BDEBUG==1
  1010.             printf("crash backing: %s%s\n",liens[ptr]->adr,liens[ptr]->fil);
  1011. #endif
  1012.             if (back_add(back,back_max,&opt,&cache,urladr,urlfil,savename,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil,liens[ptr]->testmode)==-1) {
  1013.               printf("PANIC! : Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  1014. #if BDEBUG==1
  1015.               printf("error while crash adding\n");
  1016. #endif
  1017.               if (opt.errlog) {
  1018.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Unexpected backing error for %s%s"LF,urladr,urlfil);
  1019.                 test_flush;
  1020.               } 
  1021.               
  1022.             }
  1023.           }
  1024.           
  1025. #if BDEBUG==1
  1026.           printf("test number of socks\n");
  1027. #endif
  1028.           
  1029.           // ajouter autant de socket qu'on peut ajouter
  1030.           n=opt.maxsoc-back_nsoc(back,back_max);
  1031. #if BDEBUG==1
  1032.           printf("%d sockets available for backing\n",n);
  1033. #endif
  1034.  
  1035. #if HTS_ANALYSTE==2
  1036.           if ((n>0) && (!_hts_setpause)) {   // si sockets libre et pas en pause, ajouter
  1037. #else
  1038.           if (n>0) {                         // si sockets libre
  1039. #endif
  1040.             // remplir autant que l'on peut le cache (backing)
  1041.             back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1042.           }
  1043.           
  1044.           // index du lien actuel
  1045.           b=back_index(back,back_max,urladr,urlfil,savename);
  1046.           
  1047.           if (b>=0) {
  1048. #if BDEBUG==1
  1049.             printf("back index %d, waiting\n",b);
  1050. #endif
  1051.             // ------------------------------------------------------------
  1052.             // attendre que le fichier actuel soit prΩt - BOUCLE D'ATTENTE
  1053.             do {
  1054.                 // temps α attendre, et remplir autant que l'on peut le cache (backing)
  1055.               if (back[b].status>0) back_wait(back,back_max,&opt,&cache,stat_timestart);
  1056.               back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1057.               
  1058.               // autres occupations de HTTrack: statistiques, boucle d'attente, etc.
  1059.               if ((opt.makestat) || (opt.maketrack)) {
  1060.                 double l=time_local();
  1061.                 if ((int) (l-makestat_time) >= 60) {   
  1062.                   if (makestat_fp != NULL) {
  1063.                     fspc(makestat_fp,"info");
  1064.                     fprintf(makestat_fp,"Rate= %d (/"LLintP") \11NewLinks= %d (/%d)"LF,(int) ((new_stat_bytes-makestat_total)/(l-makestat_time)), new_stat_bytes,(int) lien_tot-makestat_lnk,(int) lien_tot);
  1065.                     fflush(makestat_fp);
  1066.                     makestat_total=new_stat_bytes;
  1067.                     makestat_lnk=lien_tot;
  1068.                   }
  1069.                   if (maketrack_fp!=NULL) {
  1070.                     int i;
  1071.                     fspc(maketrack_fp,"info"); fprintf(maketrack_fp,LF);
  1072.                     for(i=0;i<back_max;i++) {
  1073.                       back_info(back,i,3,maketrack_fp);
  1074.                     }
  1075.                     fprintf(maketrack_fp,LF);
  1076.                     
  1077.                   }
  1078.                   makestat_time=l;
  1079.                 }
  1080.               }
  1081. #if HTS_ANALYSTE==2
  1082.               {
  1083.                 LLint nb;
  1084.                 int i;
  1085.                 {
  1086.                   char* s=hts_cancel_file("");
  1087.                   if (strnotempty(s)) {    // fichier α canceller
  1088.                     for(i=0;i<back_max;i++) {
  1089.                       if ((back[i].status>0)) {
  1090.                         if (strcmp(back[i].url_sav,s)==0) {  // ok trouvΘ
  1091.                           if (back[i].status != 1000) {
  1092. #if HTS_DEBUG_CLOSESOCK
  1093.                             DEBUG_W("user cancel: deletehttp\n");
  1094. #endif
  1095.                             if (back[i].r.soc!=INVALID_SOCKET) deletehttp(&back[i].r);
  1096.                             back[i].r.soc=INVALID_SOCKET;
  1097.                             back[i].r.statuscode=-1;
  1098.                             strcpy(back[i].r.msg,"Cancelled by User");
  1099.                             back[i].status=0;  // terminΘ
  1100.                           } else    // cancel ftp.. flag α 1
  1101.                             back[i].stop_ftp = 1;
  1102.                         }
  1103.                       }
  1104.                     }
  1105.                     s[0]='\0';
  1106.                   }
  1107.                 }
  1108.                 
  1109.                 nb=back_transfered(stat_bytes,back,back_max);
  1110.                 if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,nb,new_stat_bytes,(int) (time_local()-stat_timestart),back_nsoc(back,back_max),stat_files,stat_updated_files,fspc(NULL,"error") )) {
  1111.                   if (opt.errlog) {
  1112.                     fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1113.                     test_flush;
  1114.                   } 
  1115.                   exit_xh=1;  // exit requested
  1116.                   XH_uninit;
  1117.                   return 0;
  1118.                 }
  1119.  
  1120.               }
  1121. #endif
  1122. #if HTS_POLL      
  1123.               if ((opt.shell) || (opt.keyboard)) {
  1124.                 int rcvd=0;
  1125.                 double tl;
  1126.                 info_shell=1;
  1127.                 // Traitement Θventuel des requΦtes stdin etc.
  1128.                 while (check_stdin()) {  // donnΘes disponibles
  1129.                   char com[256];
  1130.                   com[0]='\0';
  1131.                   
  1132.                   if (!rcvd) rcvd=1;
  1133.                   linput(stdin,com,256);
  1134.  
  1135.                   if (strnotempty(com)) {
  1136.                     if (strlen(com)<=2) {
  1137.                       switch(*com) {
  1138.                       case '?': {    // Status?
  1139.                         if (back[b].status>0) printf("WAIT\n"); 
  1140.                         else printf("READY\n");
  1141.                                 }
  1142.                         break;
  1143.                       case 'f': {    // Fichier en attente?
  1144.                         if (back[b].status>0) printf("WAIT %s\n",back[b].url_fil); 
  1145.                         else printf("READY %s\n",back[b].url_fil);
  1146.                                 }
  1147.                         break;
  1148.                       case 'A': case 'F': {    // filters
  1149.                         int i;
  1150.                         for(i=0;i<filptr;i++) {
  1151.                           printf("%s ",filters[i]);
  1152.                         }
  1153.                         printf("\n");
  1154.                                 }
  1155.                         break;
  1156.                       case '#': {    // Afficher statistique sur le nombre de liens, etc
  1157.                         switch(*(com+1)) {
  1158.                         case 'l': printf("%d\n",lien_tot); break;  // nombre de liens enregistrΘs
  1159.                         case 's': printf("%d\n",back_nsoc(back,back_max)); break;  // nombre de sockets
  1160.                         case 'r': printf("%d\n",(int) (new_stat_bytes/(time_local()-stat_timestart))); break;  // taux de transfert
  1161.                         }
  1162.                                 }
  1163.                         break;
  1164.                       case 'K': if (*(com+1)=='!') {  // Kill
  1165.                         XH_uninit;
  1166.                         return -1;
  1167.                                 }
  1168.                         break;
  1169.                       case 'X': if (*(com+1)=='!') {  // exit
  1170.                         exit_xh=1;
  1171.                                 }
  1172.                         break;
  1173.                       case 'I': if (*(com+1)=='+') info_shell=1; else info_shell=0;
  1174.                         break;
  1175.                       }
  1176.                       io_flush;
  1177.                     } else if (*com=='@') {
  1178.                       printf("%s\n",com+1);
  1179.                       io_flush;
  1180.                     }
  1181.                   } 
  1182.                   
  1183.                 }  // while
  1184.                 tl=time_local();
  1185.                 
  1186.                 // gΘnΘrer un message d'infos sur l'Θtat actuel
  1187.                 if (opt.shell) {    // si shell
  1188.                   if ((tl-last_info_shell)>0) {    // toute les 1 sec
  1189.                     FILE* fp=stdout;
  1190.                     int a=0;
  1191.                     last_info_shell=tl;
  1192.                     if (fexist(fconcat(opt.path_log,"hts-autopsy"))) {  // dΘbuggage: teste si le robot est vivant
  1193.                       // (oui je sais un robot vivant.. mais bon.. il a le droit de vivre lui aussi)
  1194.                       // (libΘrons les robots esclaves de l'internet!)
  1195.                       remove(fconcat(opt.path_log,"hts-autopsy"));
  1196.                       fp=fopen(fconcat(opt.path_log,"hts-isalive"),"wb");
  1197.                       a=1;
  1198.                     }
  1199.                     if ((info_shell) || a) {
  1200.                       int i,j;
  1201.                       
  1202.                       fprintf(fp,"TIME %d"LF,(int) (tl-stat_timestart));
  1203.                       fprintf(fp,"TOTAL %d"LF,(int) stat_bytes);
  1204.                       fprintf(fp,"RATE %d"LF,(int) (new_stat_bytes/(tl-stat_timestart)));
  1205.                       fprintf(fp,"SOCKET %d"LF,back_nsoc(back,back_max));
  1206.                       fprintf(fp,"LINK %d"LF,lien_tot);
  1207.                       {
  1208.                         LLint mem=0;
  1209.                         for(i=0;i<back_max;i++)
  1210.                           if (back[i].r.adr!=NULL)
  1211.                             mem+=back[i].r.size;
  1212.                           fprintf(fp,"INMEM "LLintP""LF,mem);
  1213.                       }
  1214.                       for(j=0;j<2;j++) {  // passes pour ready et wait
  1215.                         for(i=0;i<back_max;i++) {
  1216.                           back_info(back,i,j+1,stdout);    // maketrack_fp a la place de stdout ?? // **
  1217.                         }
  1218.                       }
  1219.                       fprintf(fp,LF);
  1220.                       if (a)
  1221.                         fclose(fp);
  1222.                       io_flush;
  1223.                     }
  1224.                   }
  1225.                 }  // si shell
  1226.                 
  1227.               }  // si shell ou keyboard (option)
  1228.               //
  1229. #endif
  1230.             } while((back[b].status>0));
  1231. #if HTS_ANALYSTE
  1232. #else
  1233.             if (!opt.quiet) {  // petite animation
  1234.               if (!opt.verbosedisplay) {
  1235.                 static int roll=0;
  1236.                 roll=(roll+1)%4;
  1237.                 printf("%c\x0d",("/-\\|")[roll]);
  1238.                 fflush(stdout);
  1239.               } else {
  1240.                 if (back[b].r.statuscode==200)
  1241.                   printf("%d/%d: %s%s ("LLintP" bytes) - OK\33[K\r",ptr,lien_tot,back[b].url_adr,back[b].url_fil,back[b].r.size);
  1242.                 else
  1243.                   printf("%d/%d: %s%s ("LLintP" bytes) - %d\33[K\r",ptr,lien_tot,back[b].url_adr,back[b].url_fil,back[b].r.size,back[b].r.statuscode);
  1244.                 fflush(stdout);
  1245.               }
  1246.             }
  1247. #endif
  1248.             // ------------------------------------------------------------
  1249.             // VΘrificateur d'intΘgritΘ
  1250. #if DEBUG_CHECKINT
  1251.             _CHECKINT(&back[b],"Retour de back_wait, aprΦs le while")
  1252.             {
  1253.               int i;
  1254.               for(i=0;i<back_max;i++) {
  1255.                 char si[256];
  1256.                 sprintf(si,"Test global aprΦs back_wait, index %d",i);
  1257.                 _CHECKINT(&back[i],si)
  1258.               }
  1259.             }
  1260. #endif
  1261.             
  1262.             // copier structure rΘponse htsblk
  1263.             bcopy((char*) &(back[b].r), (char*) &r, sizeof(htsblk));
  1264.             r.location=loc;    // ne PAS copier location!! adresse, pas de buffer
  1265.             if (back[b].r.location) 
  1266.               strcpy(r.location,back[b].r.location);
  1267.             back[b].r.adr=NULL;    // ne pas faire de desalloc ensuite
  1268.  
  1269.             // libΘrer emplacement backing
  1270.             back_delete(back,b);
  1271.             
  1272.             // progression
  1273.             if (opt.aff_progress) {
  1274.               double tl=time_local();
  1275.               if ((tl-lastime)>0) {
  1276.                 char s[32];
  1277.                 int i=0;
  1278.                 lastime=tl;
  1279.                 _CLRSCR; _GOTOXY("1","1");
  1280.                 printf("Rate=%d B/sec\n",(int) (new_stat_bytes/(tl-stat_timestart)));
  1281.                 while(i<minimum(back_max,99)) {  // **
  1282.                   if (back[i].status>=0) {  // loading..
  1283.                     s[0]='\0';
  1284.                     if (strlen(back[i].url_fil)>16)
  1285.                       strcat(s,back[i].url_fil+strlen(back[i].url_fil)-16);       
  1286.                     else
  1287.                       strncat(s,back[i].url_fil,16);
  1288.                     printf("%s : ",s);
  1289.                     
  1290.                     printf("[");
  1291.                     if (back[i].r.totalsize>0) {
  1292.                       int p;
  1293.                       int j;
  1294.                       p=(int)((back[i].r.size*10)/back[i].r.totalsize);
  1295.                       p=minimum(10,p);
  1296.                       for(j=0;j<p;j++) printf("*");
  1297.                       for(j=0;j<(10-p);j++) printf("-");
  1298.                     } else { 
  1299.                       printf(LLintP,back[i].r.size);                      
  1300.                     }
  1301.                     printf("]");
  1302.                     
  1303.                     //} else if (back[i].status==0) {
  1304.                     //  strcpy(s,"ENDED");
  1305.                   } 
  1306.                   printf("\n");
  1307.                   i++;
  1308.                 }
  1309.                 io_flush;
  1310.               }
  1311.             }
  1312.             
  1313.             // dΘbug graphique
  1314. #if BDEBUG==2
  1315.             {
  1316.               char s[12];
  1317.               int i=0;
  1318.               _GOTOXY(1,1);
  1319.               printf("Rate=%d B/sec\n",(int) (new_stat_bytes/(time_local()-stat_timestart)));
  1320.               while(i<minimum(back_max,160)) {
  1321.                 if (back[i].status>0) {
  1322.                   sprintf(s,"%d",back[i].r.size);
  1323.                 } else if (back[i].status==0) {
  1324.                   strcpy(s,"ENDED");
  1325.                 } else 
  1326.                   strcpy(s,"   -   ");
  1327.                 while(strlen(s)<8) strcat(s," ");
  1328.                 printf("%s",s); io_flush;
  1329.                 i++;
  1330.               }
  1331.             }
  1332. #endif
  1333.             
  1334.             
  1335. #if BDEBUG==1
  1336.             printf("statuscode=%d with %s / msg=%s\n",r.statuscode,r.contenttype,r.msg);
  1337. #endif
  1338.             
  1339.           } else {
  1340. #if BDEBUG==1
  1341.             printf("back index error\n");
  1342. #endif
  1343.           }
  1344.           
  1345.         }
  1346.         // FIN --RECUPERATION LIEN--- 
  1347.         // ------------------------------------------------------------
  1348.  
  1349.  
  1350.  
  1351.       } else {    // lien vide..
  1352.         if (opt.errlog) {
  1353.           fprintf(opt.errlog,"Error Link empty"LF); test_flush;
  1354.           error=1;
  1355.         }         
  1356.       }  // test si url existe (non vide!)
  1357.       
  1358.  
  1359.  
  1360.       // ---tester taille a posteriori---
  1361.       // tester r.adr
  1362.       if (!error) {
  1363.         // erreur, pas de fichier chargΘ:
  1364.         if ((!r.adr) && (r.is_write==0) && (r.statuscode!=301) && (r.statuscode!=302) && (r.statuscode!=412)) { 
  1365.           error=1;
  1366.           
  1367.           // peut Ωtre que le fichier Θtait trop gros?
  1368.           if ((istoobig(r.totalsize,opt.maxfile_html,opt.maxfile_nonhtml,r.contenttype))
  1369.            || (istoobig(r.totalsize,opt.maxfile_html,opt.maxfile_nonhtml,r.contenttype))) {
  1370.             error=0;
  1371.             if (opt.errlog) {
  1372.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Big file cancelled according to user's preferences: %s%s"LF,urladr,urlfil);
  1373.               test_flush;
  1374.             }
  1375.           }
  1376.           error=1;    // ne pas traiter la suite -- euhh si finalement..
  1377.         }
  1378.       }
  1379.       // ---fin tester taille a posteriori---    
  1380.  
  1381.  
  1382.  
  1383.       // ---stockage en cache---
  1384.       // stocker dans le cache?
  1385.       if (ptr>0) {
  1386.         if (opt.cache) {
  1387.           if (cache.dat!=NULL) {
  1388.             // c'est le seul endroit ou l'on ajoute des elements dans le cache (fichier entier ou header)
  1389.             // on stocke tout fichier "ok", mais Θgalement les rΘponses 404,301,302...
  1390.             if ((r.statuscode==200)         /* stocker rΘponse standard, plus */
  1391.                  || (r.statuscode==204)     /* no content */
  1392.                  || (r.statuscode==301)     /* moved perm */
  1393.                  || (r.statuscode==302)     /* moved temp */
  1394.                  || (r.statuscode==401)     /* authorization */
  1395.                  || (r.statuscode==403)     /* unauthorized */
  1396.                  || (r.statuscode==404)     /* not found */
  1397.                  || (r.statuscode==410)     /* gone */
  1398.                  )
  1399.             {        /* ne pas stocker si la page gΘnΘrΘe est une erreur */
  1400.               if (!r.is_file) {
  1401.                 // stocker fichiers (et robots.txt)
  1402.                 if ( (strnotempty(savename)) || (strcmp(urlfil,"/robots.txt")==0)) {
  1403.                   // ajouter le fichier au cache
  1404.                   cache_add(r,urladr,urlfil,savename,cache.ndx,cache.dat,opt.all_in_cache);
  1405.                 }
  1406.               }
  1407.             }
  1408.           }
  1409.         }
  1410.       }
  1411.       // ---fin stockage en cache---
  1412.  
  1413.  
  1414.  
  1415.       // DEBUT rattrapage des 301,302..
  1416.       // ------------------------------------------------------------
  1417.       //if (!error) {
  1418.       {
  1419.         // on a chargΘ un fichier en plus
  1420.         // if (!error) stat_loaded+=r.size;
  1421.         
  1422.         // ------------------------------------------------------------
  1423.         // Rattrapage des 301,302 (moved) et 412 - les 304 le sont dans le backing 
  1424.         // ------------------------------------------------------------
  1425.         if ((r.statuscode==301) || (r.statuscode==302)) {          
  1426.           //if (r.adr!=NULL) {   // adr==null si fichier direct. [catch: davename normalement si cgi]
  1427.             //int i=0;
  1428.             char *rn=NULL;
  1429.             char* p;
  1430.             
  1431.             if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1432.             //if (opt.errlog) {
  1433.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"%s for %s%s"LF,r.msg,urladr,urlfil);
  1434.               test_flush;
  1435.             }
  1436.             
  1437.             
  1438. #if 0
  1439.             //do {
  1440.             //  if (strfield(r.adr+i,"href=")) {    // URL trouvΘe
  1441. #endif
  1442.             {
  1443.               char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  1444.               int n=0;
  1445.               int reponse=0;
  1446.               mov_url[0]='\0'; mov_adr[0]='\0'; mov_fil[0]='\0';
  1447.               //
  1448.               //printf("location panic! %s\n",r.location);
  1449.               
  1450.               ////p=r.adr+i;
  1451.               ////p+=5;    // sauter href
  1452.               p=r.location;
  1453.               while(is_space(*p)) p++;  // sauter espaces, " & cie
  1454.               while((!is_space(p[n])) && (p[n] != 0) && (p[n] != '>')) n++;  // compter caractΦres
  1455.               strcpy (mov_url,"");
  1456.               strncat(mov_url,p,n);    // copier URL
  1457.               
  1458.               // url qque -> adresse+fichier
  1459.               if ((reponse=ident_url_relatif(mov_url,urladr,urlfil,mov_adr,mov_fil))>=0) {                        
  1460.                 int get_it=0;         // ne pas prendre le fichier α la mΩme adresse par dΘfaut
  1461.                 int set_prio_to_0=0;  // prioritΘ 0
  1462.                 
  1463.                 //if (ident_url(mov_url,mov_adr,mov_fil)!=-1) {    // ok URL reconnue
  1464.                 // c'est (en gros) la mΩme URL..
  1465.                 // si c'est un problΦme de casse dans le host c'est que le serveur est buggΘ
  1466.                 // ("RFC says.." : host name IS case insensitive)
  1467.                 if ((strfield2(mov_adr,urladr)!=0) && (strfield2(mov_fil,urlfil)!=0)) {  // identique α casse prΦs
  1468.                   // on tourne en rond
  1469.                   if (strcmp(mov_fil,urlfil)==0) {
  1470.                     error=1;
  1471.                     get_it=-1;        // ne rien faire
  1472.                     if (opt.errlog) {
  1473.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Can not bear crazy server (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1474.                       test_flush;
  1475.                     }
  1476.                   } else {    // mauvaise casse, effacer entrΘe dans la pile et rejouer une fois
  1477.                     get_it=1;
  1478.                   }
  1479.                 } else {
  1480.                   if (ishtml(mov_url)==0) {   // pas mΩme adresse MAIS c'est un fichier (pas de page moved possible)
  1481.                     // -> on prend α cette adresse, le lien sera enregistrΘ avec lien_record() (hash)
  1482.                     if ((opt.debug>1) && (opt.log!=NULL)) {
  1483.                       fspc(opt.log,"debug"); fprintf(opt.log,"wizard link test for moved file at %s%s.."LF,mov_adr,mov_fil);
  1484.                       test_flush;
  1485.                     }
  1486.                     if (hts_acceptlink(&opt,ptr,lien_tot,liens,
  1487.                       mov_adr,mov_fil,
  1488.                       filters,&filptr,filter_max,
  1489.                       &robots,
  1490.                       &set_prio_to_0,
  1491.                       NULL) != 1) {                /* nouvelle adresse non refusΘe ? */
  1492.                       get_it=1;
  1493.                       if ((opt.debug>1) && (opt.log!=NULL)) {
  1494.                         fspc(opt.log,"debug"); fprintf(opt.log,"moved link accepted: %s%s"LF,mov_adr,mov_fil);
  1495.                         test_flush;
  1496.                       }
  1497.                     }
  1498.                   } /* sinon traitΘ normalement */
  1499.                 }
  1500.                 
  1501.                 //if ((strfield2(mov_adr,urladr)!=0) && (strfield2(mov_fil,urlfil)!=0)) {  // identique α casse prΦs
  1502.                 if (get_it==1) {
  1503.                   // court-circuiter le reste du traitement
  1504.                   // et reculer pour mieux sauter
  1505.                   if (opt.errlog) {
  1506.                     fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning wrong case ignored for %s%s (real one is %s%s)"LF,urladr,urlfil,mov_adr,mov_fil);
  1507.                     test_flush;
  1508.                   }          
  1509.                   // canceller lien actuel
  1510.                   error=1;
  1511.                   strcpy(liens[ptr]->adr,"!");  // caractΦre bidon (invalide hash)
  1512. #if HTS_HASH
  1513. #else
  1514.                   liens[ptr]->sav_len=-1;       // taille invalide
  1515. #endif
  1516.                   // noter NOUVEAU lien
  1517.                   {
  1518.                     char mov_sav[HTS_URLMAXSIZE*2];
  1519.                     // calculer lien et Θventuellement modifier addresse/fichier
  1520.                     if (url_savename(mov_adr,mov_fil,mov_sav,NULL,NULL,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe)!=-1) { 
  1521.                       if (hash_read(&hash,mov_sav,"",0)<0) {      // n'existe pas dΘja
  1522.                         // enregistrer lien (MACRO) avec SAV IDENTIQUE
  1523.                         liens_record(mov_adr,mov_fil,liens[ptr]->sav,"","");
  1524.                         //liens_record(mov_adr,mov_fil,mov_sav,"","");
  1525.                         if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1526.                           // mode test?
  1527.                           liens[lien_tot]->testmode=liens[ptr]->testmode;
  1528.                           liens[lien_tot]->link_import=0;       // mode normal
  1529.                           if (!set_prio_to_0)
  1530.                             liens[lien_tot]->prio=liens[ptr]->prio;
  1531.                           else
  1532.                             liens[lien_tot]->prio=0;            // PRIORITE NULLE (catch page)
  1533.                           liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1534.                           liens[lien_tot]->retry=liens[ptr]->retry;
  1535.                           liens[lien_tot]->premier=liens[ptr]->premier;
  1536.                           liens[lien_tot]->precedent=liens[ptr]->precedent;
  1537.                           lien_tot++;
  1538.                         } else {  // oups erreur, plus de mΘmoire!!
  1539.                           printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1540.                           if (opt.errlog) {
  1541.                             fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1542.                             test_flush;
  1543.                           }
  1544.                           //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1545.                           XH_uninit;    // dΘsallocation mΘmoire & buffers
  1546.                           return 0;
  1547.                         }
  1548.                       } else {
  1549.                         if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  1550.                           fspc(opt.errlog,"warning"); fprintf(opt.errlog,"moving %s to an existing file %s"LF,liens[ptr]->fil,urlfil);
  1551.                           test_flush;
  1552.                         }
  1553.                       }
  1554.                       
  1555.                     }
  1556.                   }
  1557.                   
  1558.                   //printf("-> %s %s %s\n",liens[lien_tot-1]->adr,liens[lien_tot-1]->fil,liens[lien_tot-1]->sav);
  1559.                   
  1560.                   // note mΘtaphysique: il se peut qu'il y ait un index.html et un INDEX.HTML
  1561.                   // sous DOS ca marche pas trΦs bien... mais comme je suis gΘnial url_savename()
  1562.                   // est α mΩme de rΘgler ce problΦme
  1563.                 } else if (get_it==0) {    // adresse vraiment diffΘrente et potentiellement en html (pas de possibilitΘ de bouger la page tel quel α cause des <img src..> et cie)
  1564.                   rn=(char*) calloct(8192,1);
  1565.                   if (rn!=NULL) {
  1566.                     // On prΘpare une page qui sautera immΘdiatement sur la bonne URL
  1567.                     // Le scanner re-changera, ensuite, cette URL, pour la mirrorer!
  1568.                     strcpy(rn,"<HTML>"CRLF);
  1569.                     strcat(rn,"<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  1570.                     strcat(rn,"<HEAD>"CRLF"<TITLE>Page has moved</TITLE>"CRLF"</HEAD>"CRLF"<BODY>"CRLF);
  1571.                     strcat(rn,"<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=");
  1572.                     strcat(rn,mov_url);    // URL
  1573.                     strcat(rn,"\">"CRLF);
  1574.                     strcat(rn,"<A HREF=\"");
  1575.                     strcat(rn,mov_url);
  1576.                     strcat(rn,"\">");
  1577.                     strcat(rn,"<B>Click here...</B></A>"CRLF);
  1578.                     strcat(rn,"</BODY>"CRLF);
  1579.                     strcat(rn,"<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  1580.                     strcat(rn,"</HTML>"CRLF);
  1581.                     
  1582.                     // changer la page
  1583.                     if (r.adr) { freet(r.adr); r.adr=NULL; }
  1584.                     r.adr=rn;
  1585.                     r.size=strlen(r.adr);
  1586.                     strcpy(r.contenttype,"text/html");
  1587.                     if (opt.errlog) {
  1588.                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"File has moved from %s%s to %s"LF,urladr,urlfil,mov_url);
  1589.                       test_flush;
  1590.                     }
  1591.  
  1592.                     // dΘclarer page comme α Θcraser par le fichier si fichier binaire
  1593.                     // on va donc modifier la structure physique du site
  1594.                     // MAIS, en cas d'update, cela fonctionnera, car:
  1595.                     // 1. page moved: pas en cache (moved)
  1596.                     // 2. fichier qui Θcrase: mΩme en cas de get avec range:, comme c'est une erreur il 
  1597.                     // n'y aura pas de rΘponse "partial content"
  1598.                     /*
  1599.                     if (ishtml(mov_url)==0) {
  1600.                       if (!fexist(fconcat(opt.path_log,"moved.lst"))) {
  1601.                         FILE* fp=fopen(fconcat(opt.path_log,"moved.lst"),"wb");
  1602.                         if (fp) fclose(fp);
  1603.                       }
  1604.                       {
  1605.                         FILE* fp=fopen(fconcat(opt.path_log,"moved.lst"),"ab");
  1606.                         if (fp) {
  1607.                           fprintf(fp,"%s\n",mov_url);
  1608.                           fclose(fp);
  1609.                         }
  1610.                       }
  1611.                     }
  1612.                     */
  1613.  
  1614.                   }
  1615.                 }
  1616.               } else {
  1617.                 if (opt.errlog) {
  1618.                   fspc(opt.errlog,"error");
  1619.                   if (reponse==-2)
  1620.                     fprintf(opt.errlog,"Protocol ftp:// not supported for %s in file %s"LF,urladr,urlfil);
  1621.                   else
  1622.                     fprintf(opt.errlog,"Unrecoverable %s for %s%s (error move to %s)"LF,r.msg,urladr,urlfil,mov_url);
  1623.                   test_flush;
  1624.                 }
  1625.                 error=1;    // URL non reconnue
  1626.               }
  1627.             }
  1628. #if 0
  1629.             // i++;
  1630.             //} while((i<r.size) && (rn==NULL) && (error==0));
  1631. #endif
  1632.                       
  1633.           // erreur HTTP (ex: 404, not found)
  1634.         } else if (r.statuscode==412) {    // Precondition Failed, c'est α dire pour nous redemander TOUT le fichier
  1635.           if (fexist(liens[ptr]->sav)) {
  1636.             remove(liens[ptr]->sav);    // Eliminer
  1637.             if (!fexist(liens[ptr]->sav)) {  // Bien ΘliminΘ? (sinon on boucle..)
  1638. #if HDEBUG
  1639.               printf("Partial content NOT up-to-date, reget all file for %s\n",liens[ptr]->sav);
  1640. #endif
  1641.               if ( (opt.debug>1) && (opt.errlog!=NULL) ) {
  1642.                 //if (opt.errlog) {
  1643.                 fspc(opt.errlog,"debug"); fprintf(opt.errlog,"Partial file reget (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1644.                 test_flush;
  1645.               }
  1646.               // enregistrer le MEME lien (MACRO)
  1647.               liens_record(liens[ptr]->adr,liens[ptr]->fil,liens[ptr]->sav,"","");
  1648.               if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1649.                 liens[lien_tot]->testmode=liens[ptr]->testmode;          // mode test?
  1650.                 liens[lien_tot]->link_import=0;       // pas mode import
  1651.                 liens[lien_tot]->prio=liens[ptr]->prio;
  1652.                 liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1653.                 liens[lien_tot]->retry=liens[ptr]->retry;
  1654.                 liens[lien_tot]->premier=liens[ptr]->premier;
  1655.                 liens[lien_tot]->precedent=ptr;
  1656.                 lien_tot++;
  1657.                 //
  1658.                 // canceller lien actuel
  1659.                 error=1;
  1660.                 strcpy(liens[ptr]->adr,"!");  // caractΦre bidon (invalide hash)
  1661. #if HTS_HASH
  1662. #else
  1663.                 liens[ptr]->sav_len=-1;       // taille invalide
  1664. #endif
  1665.                 //
  1666.               } else {  // oups erreur, plus de mΘmoire!!
  1667.                 printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1668.                 if (opt.errlog) {
  1669.                   fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1670.                   test_flush;
  1671.                 }
  1672.                 //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1673.                 XH_uninit;    // dΘsallocation mΘmoire & buffers
  1674.                 return 0;
  1675.               } 
  1676.             } else {
  1677.               if (opt.errlog!=NULL) {
  1678.                 fspc(opt.errlog,"error"); fprintf(opt.errlog,"Can not remove old file %s"LF,urlfil);
  1679.                 test_flush;
  1680.               }
  1681.             }
  1682.           } else {
  1683.             if (opt.errlog!=NULL) {
  1684.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Unexpected 412 error (%s) for %s%s"LF,r.msg,urladr,urlfil);
  1685.               test_flush;
  1686.             }
  1687.           }
  1688.         } else if (r.statuscode!=200) {
  1689.           int can_retry=0;
  1690.  
  1691.           // cas o∙ l'on peut reessayer
  1692.           // -2=timeout -3=rateout (interne α httrack)
  1693.           switch(r.statuscode) {
  1694.           //case -1: can_retry=1; break;
  1695.           case -2: if (opt.hostcontrol) {    // timeout et retry ΘpuisΘs
  1696.             if ((opt.hostcontrol & 1) && (liens[ptr]->retry<=0)) {
  1697.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1698.                 fspc(opt.log,"debug"); fprintf(opt.log,"Link banned: %s%s"LF,urladr,urlfil); test_flush;
  1699.               }
  1700.               host_ban(&opt,liens,ptr,lien_tot,back,back_max,filters,filter_max,&filptr,jump_identification(urladr));
  1701.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1702.                 fspc(opt.log,"debug"); fprintf(opt.log,"Info: previous log - link banned: %s%s"LF,urladr,urlfil); test_flush;
  1703.               }
  1704.             } else can_retry=1;
  1705.                    } else can_retry=1;
  1706.             break;
  1707.           case -3: if ((opt.hostcontrol) && (liens[ptr]->retry<=0)) {    // too slow
  1708.             if (opt.hostcontrol & 2) {
  1709.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1710.                 fspc(opt.log,"debug"); fprintf(opt.log,"Link banned: %s%s"LF,urladr,urlfil); test_flush;
  1711.               }
  1712.               host_ban(&opt,liens,ptr,lien_tot,back,back_max,filters,filter_max,&filptr,jump_identification(urladr));
  1713.               if ((opt.debug>1) && (opt.log!=NULL)) {
  1714.                 fspc(opt.log,"debug"); fprintf(opt.log,"Info: previous log - link banned: %s%s"LF,urladr,urlfil); test_flush;
  1715.               }
  1716.             } else can_retry=1;
  1717.                    } else can_retry=1;
  1718.             break;
  1719.           case -4:            // connect closed
  1720.             can_retry=1;
  1721.             break;
  1722.           case -5:            // other (non fatal) error
  1723.             can_retry=1;
  1724.             break;
  1725.           case 408: case 409: case 500: case 502: case 504: can_retry=1;
  1726.             break;
  1727.           }
  1728.           
  1729.           if ( strcmp(liens[ptr]->fil,"/primary") ) {    // pas primary (page 0)
  1730.             if ((liens[ptr]->retry<=0) || (!can_retry) ) {  // retry ΘpuisΘs (ou retry impossible)
  1731.               if (opt.errlog) {
  1732.                 if ((opt.retry>0) && (can_retry)){
  1733.                   fspc(opt.errlog,"error"); 
  1734.                   fprintf(opt.errlog,"\"%s\" (%d) after %d retries at link %s%s (from %s%s)"LF,r.msg,r.statuscode,opt.retry,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1735.                 } else {
  1736.                   if (r.statuscode==-10) {    // test OK
  1737.                     if ((opt.debug>0) && (opt.errlog!=NULL)) {
  1738.                       fspc(opt.errlog,"info"); 
  1739.                       fprintf(opt.errlog,"Test OK at link %s%s (from %s%s)"LF,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1740.                     }
  1741.                   } else {
  1742.                     if (strcmp(urlfil,"/robots.txt")) {       // ne pas afficher d'infos sur robots.txt par dΘfaut
  1743.                       fspc(opt.errlog,"error"); 
  1744.                       fprintf(opt.errlog,"\"%s\" (%d) at link %s%s (from %s%s)"LF,r.msg,r.statuscode,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1745.                     } else {
  1746.                       if (opt.debug>0) {  // on fera un alert si le retry Θchoue               
  1747.                         fspc(opt.errlog,"info"); fprintf(opt.errlog,"No robots.txt rules at %s"LF,urladr);
  1748.                         test_flush;
  1749.                       }
  1750.                     }
  1751.                   }
  1752.                 }
  1753.                 test_flush;
  1754.               }
  1755.               
  1756.               // ici on teste si on doit enregistrer la page tout de mΩme
  1757.               if (opt.errpage) {
  1758.                 store_errpage=1;
  1759.               }
  1760.               
  1761.             } else {    // retry!!
  1762.               if (opt.debug>0) {  // on fera un alert si le retry Θchoue               
  1763.                 fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Retry after error %d (%s) at link %s%s (from %s%s)"LF,r.statuscode,r.msg,urladr,urlfil,liens[liens[ptr]->precedent]->adr,liens[liens[ptr]->precedent]->fil);
  1764.                 test_flush;
  1765.               }
  1766.               // redemander fichier
  1767.               liens_record(urladr,urlfil,savename,"","");
  1768.               if (liens[lien_tot]!=NULL) {    // OK, pas d'erreur
  1769.                 liens[lien_tot]->testmode=liens[ptr]->testmode;          // mode test?
  1770.                 liens[lien_tot]->link_import=0;       // pas mode import
  1771.                 liens[lien_tot]->prio=liens[ptr]->prio;
  1772.                 liens[lien_tot]->pass2=max(liens[ptr]->pass2,numero_passe);
  1773.                 liens[lien_tot]->retry=liens[ptr]->retry-1;    // moins 1 retry!
  1774.                 liens[lien_tot]->premier=liens[ptr]->premier;
  1775.                 liens[lien_tot]->precedent=liens[ptr]->precedent;
  1776.                 lien_tot++;
  1777.               } else {  // oups erreur, plus de mΘmoire!!
  1778.                 printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1779.                 if (opt.errlog) {
  1780.                   fspc(opt.errlog,"panic"); 
  1781.                   fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1782.                   test_flush;
  1783.                 }
  1784.                 //if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1785.                 XH_uninit;    // dΘsallocation mΘmoire & buffers
  1786.                 return 0;
  1787.               } 
  1788.             }
  1789.           } else {
  1790.             if (opt.errlog) {
  1791.               fspc(opt.errlog,"info"); 
  1792.               fprintf(opt.errlog,"Info: no robots.txt at %s%s"LF,urladr,urlfil);
  1793.             }
  1794.           }
  1795.           if (!store_errpage) {
  1796.             if (r.adr) { freet(r.adr); r.adr=NULL; }  // dΘsalloc
  1797.             error=1;  // erreur!
  1798.           }
  1799.         }
  1800.         // FIN rattrapage des 301,302..
  1801.         // ------------------------------------------------------------
  1802.         
  1803.         
  1804.  
  1805.       }  // if !error
  1806.     }  // if !error
  1807.     
  1808.     if (!error) {  
  1809. #if DEBUG_SHOWTYPES
  1810.       if (strstr(REG,r.contenttype)==NULL) {
  1811.         strcat(REG,r.contenttype);
  1812.         strcat(REG,"\n");
  1813.         printf("%s\n",r.contenttype);
  1814.         io_flush;
  1815.       }
  1816. #endif
  1817.       
  1818.       // ------------------------------------------------------
  1819.       // ok, fichier chargΘ localement
  1820.       // ------------------------------------------------------
  1821.       
  1822.       // VΘrificateur d'intΘgritΘ
  1823.       #if DEBUG_CHECKINT
  1824.       {
  1825.         int i;
  1826.         for(i=0;i<back_max;i++) {
  1827.           char si[256];
  1828.           sprintf(si,"Test global aprΦs back_wait, index %d",i);
  1829.           _CHECKINT(&back[i],si)
  1830.         }
  1831.       }
  1832.       #endif
  1833.  
  1834.  
  1835.       /* info: updated */
  1836.       if (ptr>0) {
  1837.         // "mis α jour"
  1838.         if ((!r.notmodified) && (opt.is_update) && (!store_errpage)) {    // page modifiΘe
  1839.           if (strnotempty(savename)) {
  1840.             stat_updated_files++;
  1841.             if (opt.log!=NULL) {
  1842.               //if ((opt.debug>0) && (opt.log!=NULL)) {
  1843.               fspc(opt.log,"info"); fprintf(opt.log,"File updated: %s%s"LF,urladr,urlfil);
  1844.               test_flush;
  1845.             }
  1846.           }
  1847.         } else {
  1848.           if (!store_errpage) {
  1849.             if ( (opt.debug>0) && (opt.log!=NULL) ) {
  1850.               fspc(opt.log,"info"); fprintf(opt.log,"File recorded: %s%s"LF,urladr,urlfil);
  1851.               test_flush;
  1852.             }
  1853.           }
  1854.         }
  1855.       }
  1856.       
  1857.       // ------------------------------------------------------
  1858.       // traitement (parsing)
  1859.       // ------------------------------------------------------
  1860.  
  1861.       // traiter
  1862.       if ((is_hypertext_mime(r.contenttype)) && (level>0) && (r.adr!=NULL) && (r.size>0) && (!store_errpage) && (savename[0]!='\0')) {    // ne traiter que le html si autorisΘ
  1863.         // -- -- -- --
  1864.         // Parsing HTML
  1865.         if (!error) {
  1866.           // I'll have to segment this part
  1867. #include "htsparse.c"
  1868.         }
  1869.         // Fin parsing HTML
  1870.         // -- -- -- --
  1871.  
  1872.  
  1873.       }  // si text/html
  1874.       // -- -- --
  1875.       else {    // sauver fichier quelconque
  1876.         // -- -- --
  1877.         // sauver fichier
  1878.  
  1879.  
  1880.         /* En cas d'erreur, vΘrifier que fichier d'erreur existe */
  1881.         if (strnotempty(savename) == 0) {           // chemin de sauvegarde existant
  1882.           if (strcmp(urlfil,"/robots.txt")==0) {    // pas robots.txt
  1883.             if (store_errpage) {                    // c'est une page d'erreur
  1884.               int create_html_warning=0;
  1885.               int create_gif_warning=0;
  1886.               switch (ishtml(urlfil)) {      /* pas fichier html */
  1887.               case 0:                        /* non html */
  1888.                 {
  1889.                   char buff[256];
  1890.                   guess_httptype(buff,urlfil);
  1891.                   if (strcmp(buff,"image/gif")==0)
  1892.                     create_gif_warning=1;
  1893.                 }
  1894.                 break;
  1895.               case 1:                        /* html */
  1896.                 if (!r.adr) {
  1897.                 }
  1898.                 break;
  1899.               default:                       /* don't know.. */
  1900.                 break;    
  1901.               }
  1902.               /* CrΘer message d'erreur ? */
  1903.               if (create_html_warning) {
  1904.                 char* adr=(char*)malloc(strlen(HTS_DATA_ERROR_HTML)+1100);
  1905.                 if ( (opt.debug>0) && (opt.log!=NULL) ) {
  1906.                   fspc(opt.log,"info"); fprintf(opt.log,"Creating HTML warning file (%s)"LF,r.msg);
  1907.                   test_flush;
  1908.                 }
  1909.                 if (adr) {
  1910.                   if (r.adr) {
  1911.                     freet(r.adr);
  1912.                     r.adr=NULL;
  1913.                   }
  1914.                   sprintf(adr,HTS_DATA_ERROR_HTML,r.msg);
  1915.                   r.adr=adr;
  1916.                 }
  1917.               } else if (create_gif_warning) {
  1918.                 char* adr=(char*)malloc(HTS_DATA_UNKNOWN_GIF_LEN);
  1919.                 if ( (opt.debug>0) && (opt.log!=NULL) ) {
  1920.                   fspc(opt.log,"info"); fprintf(opt.log,"Creating GIF dummy file (%s)"LF,r.msg);
  1921.                   test_flush;
  1922.                 }
  1923.                 if (r.adr) {
  1924.                   freet(r.adr);
  1925.                   r.adr=NULL;
  1926.                 }
  1927.                 bcopy(HTS_DATA_UNKNOWN_GIF,adr,HTS_DATA_UNKNOWN_GIF_LEN);
  1928.                 r.adr=adr;
  1929.               }
  1930.             }
  1931.           }
  1932.         }
  1933.  
  1934.         if (strnotempty(savename) == 0) {    // pas de chemin de sauvegarde
  1935.           if (strcmp(urlfil,"/robots.txt")==0) {    // robots.txt
  1936.             if (r.adr) {
  1937.               int bptr=0;
  1938.               char line[256];
  1939.               char buff[8192];
  1940.               char infobuff[8192];
  1941.               int record=0;
  1942.               line[0]='\0'; buff[0]='\0'; infobuff[0]='\0';
  1943.               //
  1944. #if DEBUG_ROBOTS
  1945.               printf("robots.txt dump:\n%s\n",r.adr);
  1946. #endif
  1947.               do {
  1948.                 bptr+=binput(r.adr+bptr,line,200);
  1949.                 if (strfield(line,"user-agent:")) {
  1950.                   char* a;
  1951.                   a=line+11;
  1952.                   while(*a==' ') a++;    // sauter espace(s)
  1953.                   if (*a == '*') {
  1954.                     if (record != 2)
  1955.                       record=1;    // c pour nous
  1956.                   } else if (strfield(a,"httrack")) {
  1957.                     buff[0]='\0';      // re-enregistrer
  1958.                     infobuff[0]='\0';
  1959.                     record=2;          // locked
  1960. #if DEBUG_ROBOTS
  1961.                     printf("explicit disallow for httrack\n");
  1962. #endif
  1963.                   }
  1964.                   else record=0;
  1965.                 } else if (record) {
  1966.                   if (strfield(line,"disallow:")) {
  1967.                     char* a;
  1968.                     a=strchr(line,'#');
  1969.                     if (a) *a='\0';
  1970.                     while((line[strlen(line)-1]==' ') || (line[strlen(line)-1]==10) || (line[strlen(line)-1]==13))
  1971.                       line[strlen(line)-1]='\0';   // supprimer espaces
  1972.                     a=line+9;
  1973.                     while((*a==' ') || (*a==10) || (*a==13))
  1974.                       a++;    // sauter espace(s)
  1975.                     if (strnotempty(a)) {
  1976.                       if (strcmp(a,"/")) {      /* ignoring disallow: / */
  1977.                         strcat(buff,a);
  1978.                         strcat(buff,"\n");
  1979.                         if (strnotempty(infobuff)) strcat(infobuff,", ");
  1980.                         strcat(infobuff,a);
  1981.                       } else {
  1982.                         if (opt.errlog!=NULL) {
  1983.                           fspc(opt.errlog,"info"); fprintf(opt.errlog,"Note: %s robots.txt rules are too restrictive, ignoring /"LF,urladr);
  1984.                           test_flush;
  1985.                         }
  1986.                       }
  1987.                     }
  1988.                   }
  1989.                 }
  1990.               } while( (bptr<((int) strlen(r.adr))) && (strlen(buff)<4096) );
  1991.               if (strnotempty(buff)) {
  1992.                 checkrobots_set(&robots,urladr,buff);
  1993.                 if (opt.log!=NULL) {
  1994.                   if (opt.log != opt.errlog) {
  1995.                     fspc(opt.log,"info"); fprintf(opt.log,"Note: robots.txt forbidden links for %s are: %s"LF,urladr,infobuff);
  1996.                     test_flush;
  1997.                   } 
  1998.                 }
  1999.                 if (opt.errlog!=NULL) {
  2000.                   fspc(opt.errlog,"info"); fprintf(opt.errlog,"Note: due to %s remote robots.txt rules, links begining with these path will be forbidden: %s (see in the options to disable this)"LF,urladr,infobuff);
  2001.                   test_flush;
  2002.                 }
  2003.               }
  2004.             }
  2005.           }
  2006.         } else if (r.is_write) {    // dΘja sauvΘ sur disque
  2007.           stat_files++;
  2008.           stat_bytes+=r.size;
  2009.           //printf("ok......\n");
  2010.         } else {
  2011.           // Si on doit sauver une page HTML sans la scanner, cela signifie que le niveau de
  2012.           // rΘcursion nous en empΩche
  2013.           // Dans ce cas on met un fichier indiquant ce fait
  2014.           // Si par la suite on doit retraiter ce fichier avec un niveau de rΘcursion plus
  2015.           // fort, on supprimera le readme, et on scannera le fichier html!
  2016.           // note: sautΘ si store_errpage (cαd si page d'erreur, non α scanner!)
  2017.           if ( (is_hypertext_mime(r.contenttype)) && (!store_errpage) && (r.size>0)) {  // c'est du html!!
  2018.             char tempo[HTS_URLMAXSIZE*2];
  2019.             FILE* fp;
  2020.             tempo[0]='\0';
  2021.             strcpy(tempo,savename);
  2022.             strcat(tempo,".readme");
  2023.             
  2024. #if HTS_DOSNAME
  2025.             // remplacer / par des slash arriΦre
  2026.             {
  2027.               int i=0;
  2028.               while(tempo[i]) {
  2029.                 if (tempo[i]=='/')
  2030.                   tempo[i]='\\';
  2031.                 i++;
  2032.               } 
  2033.             } 
  2034.             // a partir d'ici le slash devient antislash
  2035. #endif
  2036.             
  2037.             if ((fp=fopen(tempo,"wb"))!=NULL) {
  2038.               fprintf(fp,"Info-file generated by HTTrack Website Copier "HTTRACK_VERSION""CRLF""CRLF);
  2039.               fprintf(fp,"The file %s has not been scanned by HTS"CRLF,savename);
  2040.               fprintf(fp,"Some links contained in it may be unreachable locally."CRLF);
  2041.               fprintf(fp,"If you want to get these files, you have to set an upper recurse level, ");
  2042.               fprintf(fp,"and to rescan the URL."CRLF);
  2043.               fclose(fp);
  2044. #if HTS_WIN==0
  2045.               chmod(tempo,HTS_ACCESS_FILE);      
  2046. #endif
  2047.               usercommand(0,NULL,antislash(tempo));
  2048.             }
  2049.             
  2050.             
  2051.             if ( (opt.debug>0) && (opt.errlog!=NULL) ) {
  2052.               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Warning: store %s without scan: %s"LF,r.contenttype,savename);
  2053.               test_flush;
  2054.             }
  2055.           } else {
  2056.             if ((opt.getmode & 2)!=0) {    // ok autorisΘ
  2057.               if ( (opt.debug>1) && (opt.log!=NULL) ) {
  2058.                 fspc(opt.log,"debug"); fprintf(opt.log,"Store %s: %s"LF,r.contenttype,savename);
  2059.                 test_flush;
  2060.               }
  2061.             } else {    // lien non autorisΘ! (ex: cgi-bin en html)
  2062.               if ((opt.debug>1) && (opt.log!=NULL)) {
  2063.                 fspc(opt.log,"debug"); fprintf(opt.log,"non-html file ignored after upload at %s : %s"LF,urladr,urlfil);
  2064.                 test_flush;
  2065.               } 
  2066.               freet(r.adr); r.adr=NULL;
  2067.             }
  2068.           }
  2069.           
  2070.           //printf("extern=%s\n",r.contenttype);
  2071.  
  2072.           // ATTENTION C'EST ICI QU'ON SAUVE LE FICHIER!!          
  2073.           if (r.adr) {
  2074.             if (filesave(r.adr,(int)r.size,savename)!=0) {
  2075.               if (opt.errlog) {   
  2076.                 fprintf(opt.errlog,"Unable to save file %s"LF,savename);
  2077.                 test_flush;
  2078.               }
  2079.             } else {      
  2080.               stat_files++;
  2081.               stat_bytes+=r.size;
  2082.             }
  2083.           }
  2084.           
  2085.         }
  2086.   
  2087.         //printf("check: %s\n",savename);
  2088.         // parser classes java
  2089.         if (opt.parsejava) {
  2090.           if (strlen(savename)>6) {  // fichier.class
  2091.             if (strfield(savename+strlen(savename)-6,".class")) {  // ok c'est une classe
  2092.               if (fexist(savename)) {   // ok, existe bien!
  2093.                 char err_msg[1100];
  2094.                 int r;
  2095.                 err_msg[0]='\0';
  2096.                 
  2097.                 //##char* buffer;
  2098.                 // JavaParsing f34R!
  2099.                 if ((opt.debug>1) && (opt.log!=NULL)) {
  2100.                   fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): parsing %s"LF,savename); test_flush;
  2101.                 }
  2102.                 
  2103.                 //##buffer=(char*) malloct(32768);
  2104.                 //##if (buffer) {
  2105.                 //
  2106.                 //##strcpy(buffer,"$BUFFER$");
  2107.                 //##hts_add_file(buffer);    // dΘclarer buffer
  2108.                 while(hts_add_file(NULL,-1) >= 0);   // clear chain
  2109.                 
  2110.                 r=hts_parse_java(savename,(char*) &err_msg);  // parsing
  2111.                 if (!r) {    // error
  2112.                   if (opt.errlog) {   
  2113.                     fprintf(opt.errlog,"Unable to parse java file %s : %s"LF,savename,err_msg);
  2114.                     test_flush;
  2115.                   }
  2116.                 } else {  // ok
  2117.                   char adr[HTS_URLMAXSIZE*2],fil[HTS_URLMAXSIZE*2],save[HTS_URLMAXSIZE*2];  // nom du fichier α sauver dans la boucle
  2118.                   char codebase[HTS_URLMAXSIZE*2];                  // codebase classe java
  2119.                   char lien[HTS_URLMAXSIZE*2];
  2120.                   //##char* a;
  2121.                   int file_position;
  2122.                   int pass_fix,prio_fix;
  2123.                   codebase[0]='\0';
  2124.                   //
  2125.                   
  2126.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  2127.                     fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): parsing finished, now copying links.."LF); test_flush;
  2128.                   }
  2129.                   // recopie de "creer le lien"
  2130.                   //
  2131.                   
  2132.                   // adr = c'est la mΩme
  2133.                   // fil et save: save2 et fil2
  2134.                   prio_fix=maximum(liens[ptr]->prio-1,0);
  2135.                   pass_fix=max(liens[ptr]->pass2,numero_passe);
  2136.                   if (liens[ptr]->cod) strcpy(codebase,liens[ptr]->cod);       // codebase valable pour tt les classes descendantes
  2137.                   if (strnotempty(codebase)==0) {    // pas de codebase, construire
  2138.                     char* a;
  2139.                     strcpy(codebase,liens[ptr]->fil);
  2140.                     a=codebase+strlen(codebase)-1;
  2141.                     while((*a) && (*a!='/') && ((int) a > (int) codebase)) a--;
  2142.                     if (*a=='/')
  2143.                       *(a+1)='\0';    // couper
  2144.                   } else {    // couper http:// Θventuel
  2145.                     if (strfield(codebase,"http://")) {
  2146.                       char tempo[HTS_URLMAXSIZE*2];
  2147.                       char* a=codebase+7;
  2148.                       a=strchr(a,'/');    // aprΦs host
  2149.                       if (a) {  // ** msg erreur et vΘrifier?
  2150.                         strcpy(tempo,a);
  2151.                         strcpy(codebase,tempo);    // couper host
  2152.                       } else {
  2153.                         if (opt.errlog) {   
  2154.                           fprintf(opt.errlog,"Unexpected strstr error in base %s"LF,codebase);
  2155.                           test_flush;
  2156.                         }
  2157.                       }
  2158.                     }
  2159.                   }
  2160.                   //##a=buffer;
  2161.                   //##strcat(buffer,"&");  // fin du buffer
  2162.                   if (!((int) strlen(codebase)<HTS_URLMAXSIZE)) {    // trop long
  2163.                     if (opt.errlog) {   
  2164.                       fprintf(opt.errlog,"Codebase too long, parsing skipped (%s)"LF,codebase);
  2165.                       test_flush;
  2166.                     }
  2167.                     //##a=NULL;
  2168.                     while(hts_add_file(NULL,-1) >= 0);   // clear chain
  2169.                   }
  2170.                   while ( (file_position=hts_add_file(lien,-1)) >= 0 ) {
  2171.                     int dejafait=0;
  2172.                     /* //##
  2173.                     char* b;
  2174.                     
  2175.                      // prochain fichier α noter!
  2176.                      lien[0]='\0';
  2177.                      b=strchr(a,'&');  // marqueur de fin de chaine (voir hts_add_file)
  2178.                      if (b) {
  2179.                      if ( ( ((int) b-(int) a) + strlen(codebase)) < HTS_URLMAXSIZE)
  2180.                      strncat(lien,a,(int) b-(int) a);    // nom du fichier
  2181.                      else {
  2182.                      if (opt.errlog) {   
  2183.                      fprintf(opt.errlog,"Error: Java-Parser generated link that exceeds %d bytes"LF,HTS_URLMAXSIZE);
  2184.                      test_flush;
  2185.                      }
  2186.                      }
  2187.                      } else a=NULL;
  2188.                      
  2189.                       if (strnotempty(lien)==0) a=NULL;  // fin
  2190.                       if (a)
  2191.                       a=b+1;
  2192.                     */
  2193.                     
  2194.                     if (strnotempty(lien)) {
  2195.                       
  2196.                       // calculer les chemins et noms de sauvegarde
  2197.                       if (ident_url_relatif(lien,urladr,codebase,adr,fil)>=0) { // reformage selon chemin
  2198.                         int r;
  2199.                         
  2200.                         //  patcher opt pour garder structure originale!! (on ne patche pas les noms dans la classe java!)
  2201.                         //##if (!strstr(lien,"://")) {         // PAS tester les http://.. inutile (on ne va pas patcher le binaire :-( )
  2202.                         if (1) {
  2203.                           char tempo[HTS_URLMAXSIZE*2];
  2204.                           int a,b;
  2205.                           tempo[0]='\0';
  2206.                           a=opt.savename_type;
  2207.                           b=opt.savename_83;
  2208.                           opt.savename_type=0;
  2209.                           opt.savename_83=0;
  2210.                           // note: adr,fil peuvent Ωtre patchΘs
  2211.                           r=url_savename(adr,fil,save,NULL,NULL,NULL,NULL,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe);
  2212.                           opt.savename_type=a;
  2213.                           opt.savename_83=b;
  2214.                           if (r != -1) {
  2215.                             if (savename) {
  2216.                               if (lienrelatif(tempo,save,savename)==0) {
  2217.                                 if ((opt.debug>1) && (opt.log!=NULL)) {
  2218.                                   fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): relative link at %s build with %s and %s: %s"LF,adr,save,savename,tempo);
  2219.                                   test_flush;
  2220.                                 }
  2221.                                 //
  2222.                                 // xxc xxc xxc xxc TODO:
  2223.                                 // rebuild the java class with patched strings...
  2224.                                 //
  2225.                                 if (strlen(tempo)<=strlen(lien)) {
  2226.                                   FILE* fp=fopen(savename,"r+b");
  2227.                                   if (fp) {
  2228.                                     if (!fseek(fp,file_position,SEEK_SET)) {
  2229.                                       //unsigned short int string_length=strlen(tempo);
  2230.                                       //fwrite(&valint,sizeof(string_length),1,fp);
  2231.                                       // xxc xxc xxc
  2232.                                       // ARGH! SI la taille est <, dΘcaler le code ?!
  2233.                                       // xxc xxc xxc
  2234.                                     } else {
  2235.                                       if (opt.log!=NULL) {
  2236.                                         fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): unable to patch: %s"LF,savename);
  2237.                                         test_flush;
  2238.                                       }
  2239.                                     }
  2240.                                     fclose(fp);
  2241.                                   } else {
  2242.                                     if (opt.log!=NULL) {
  2243.                                       fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): unable to open: %s"LF,savename);
  2244.                                       test_flush;
  2245.                                     }
  2246.                                   }
  2247.                                 } else {
  2248.                                   if (opt.log!=NULL) {
  2249.                                     fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): link too long, unable to write it: %s"LF,tempo);
  2250.                                     test_flush;
  2251.                                   }
  2252.                                 }
  2253.                               }
  2254.                             }
  2255.                           }
  2256.                         } else {
  2257.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  2258.                             fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): file not caught: %s"LF,lien); test_flush;
  2259.                           }
  2260.                           r=-1;
  2261.                         }
  2262.                         //
  2263.                         if (r != -1) {
  2264.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  2265.                             fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): %s%s -> %s (base %s)"LF,adr,fil,save,codebase); test_flush;
  2266.                           }
  2267.                           
  2268.                           // modifiΘ par rapport α l'autre version (cf prio_fix notamment et save2)
  2269.                           
  2270.                           // vΘrifier que le lien n'a pas dΘja ΘtΘ notΘ
  2271.                           // si c'est le cas, alors il faut s'assurer que la prioritΘ associΘe
  2272.                           // au fichier est la plus grande des deux prioritΘs
  2273.                           //
  2274.                           // On part de la fin et on essaye de se presser (Θconomise temps machine)
  2275. #if HTS_HASH
  2276.                           {
  2277.                             int i=hash_read(&hash,save,"",0);      // lecture type 0 (sav)
  2278.                             if (i>=0) {
  2279.                               liens[i]->prio=maximum(liens[i]->prio,prio_fix);
  2280.                               dejafait=1;
  2281.                             }
  2282.                           }
  2283. #else
  2284.                           {
  2285.                             register int l;
  2286.                             register int i;
  2287.                             l=strlen(save);
  2288.                             for(i=lien_tot-1;(i>=0) && (dejafait==0);i--) {
  2289.                               if (liens[i]->sav_len==l) {    // mΩme taille de chaεne
  2290.                                 if (strcmp(liens[i]->sav,save)==0) {    // existe dΘja
  2291.                                   liens[i]->prio=maximum(liens[i]->prio,prio_fix);
  2292.                                   dejafait=1;
  2293.                                 }
  2294.                               }
  2295.                             }
  2296.                           }
  2297. #endif
  2298.                           
  2299.                           
  2300.                           if (!dejafait) {
  2301.                             //
  2302.                             // >>>> CREER LE LIEN JAVA <<<<
  2303.                             
  2304.                             // enregistrer fichier de java (MACRO)
  2305.                             liens_record(adr,fil,save,"","");
  2306.                             if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  2307.                               printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  2308.                               if (opt.errlog) { 
  2309.                                 fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  2310.                                 test_flush;
  2311.                               }
  2312.                               // if ((opt.getmode & 1) && (ptr>0)) { if (fp) { fclose(fp); fp=NULL; } }
  2313.                               XH_extuninit;    // dΘsallocation mΘmoire & buffers
  2314.                               return 0;
  2315.                             }  
  2316.                             
  2317.                             // mode test?                          
  2318.                             liens[lien_tot]->testmode=0;          // pas mode test
  2319.                             
  2320.                             liens[lien_tot]->link_import=0;       // pas mode import
  2321.                             
  2322.                             // Θcrire autres paramΦtres de la structure-lien
  2323.                             //if (meme_adresse)                                 
  2324.                             liens[lien_tot]->premier=liens[ptr]->premier;
  2325.                             //else    // sinon l'objet pΦre est le prΘcΘdent lui mΩme
  2326.                             //  liens[lien_tot]->premier=ptr;
  2327.                             
  2328.                             liens[lien_tot]->precedent=ptr;
  2329.                             // noter la prioritΘ
  2330.                             liens[lien_tot]->prio=prio_fix;
  2331.                             liens[lien_tot]->pass2=max(pass_fix,numero_passe);
  2332.                             liens[lien_tot]->retry=opt.retry;
  2333.                             
  2334.                             //strcpy(liens[lien_tot]->adr,adr);
  2335.                             //strcpy(liens[lien_tot]->fil,fil);
  2336.                             //strcpy(liens[lien_tot]->sav,save); 
  2337.                             if ((opt.debug>1) && (opt.log!=NULL)) {
  2338.                               fspc(opt.log,"debug"); fprintf(opt.log,"(JavaClass catch file): OK, NOTE: %s%s -> %s"LF,liens[lien_tot]->adr,liens[lien_tot]->fil,liens[lien_tot]->sav);
  2339.                               test_flush;
  2340.                             }
  2341.                             
  2342.                             lien_tot++;  // UN LIEN DE PLUS
  2343.                           }
  2344.                         }      
  2345.                         }  
  2346.                         
  2347.                       }  
  2348.                     }
  2349.                     
  2350.                   }
  2351.                   //##// effacer buffer temporaire
  2352.                   //##if (buffer) freet(buffer); buffer=NULL;
  2353.                   //##}  // if buffer
  2354.               }  // if exist
  2355.             }  // if .class
  2356.           }  // if strlen-savename
  2357.         }  // if opt.parsejava
  2358.         
  2359.         
  2360.         
  2361.       }  // text/html ou autre
  2362.       
  2363.     }  // if !error
  2364.     
  2365.     
  2366.     // libΘrer les liens
  2367.     if (r.adr) { freet(r.adr); r.adr=NULL; }   // libΘrer la mΘmoire!
  2368.     
  2369.     // prochain lien
  2370.     ptr++;
  2371.     
  2372.     // faut-il sauter le(s) lien(s) suivant(s)? (fichiers images α passer aprΦs les html)
  2373.     if (opt.getmode & 4) {    // sauver les non html aprΦs
  2374.       // sauter les fichiers selon la passe
  2375.       if (!numero_passe) {
  2376.         while((ptr<lien_tot)?(   liens[ptr]->pass2):0) ptr++;
  2377.       } else {
  2378.         while((ptr<lien_tot)?( ! liens[ptr]->pass2):0) ptr++;
  2379.       }
  2380.       if (ptr>=lien_tot) {     // fin de boucle
  2381.         if (!numero_passe) { // premiΦre boucle
  2382.           if ((opt.debug>1) && (opt.log!=NULL)) {
  2383.             fprintf(opt.log,LF"Now getting non-html files..."LF);
  2384.             test_flush;
  2385.           }
  2386.           numero_passe=1;   // seconde boucle
  2387.           ptr=0;
  2388.           // prochain pass2
  2389.           while((ptr<lien_tot)?(!liens[ptr]->pass2):0) ptr++;
  2390.           
  2391.           //printf("first link==%d\n");
  2392.           
  2393.         }
  2394.       }  
  2395.     }
  2396.         
  2397.     // a-t-on dΘpassΘ le quota?
  2398.     if ((opt.maxsite>0) && (stat_bytes>=opt.maxsite)) {
  2399.       if (opt.errlog) {
  2400.         fprintf(opt.errlog,"More than %d bytes have been transfered.. giving up"LF,opt.maxsite);
  2401.         test_flush;
  2402.       } 
  2403.       ptr=lien_tot;
  2404.     } else if ((opt.maxtime>0) && ((time_local()-stat_timestart)>opt.maxtime)) {            
  2405.       if (opt.errlog) {
  2406.         fprintf(opt.errlog,"More than %d seconds passed.. giving up"LF,opt.maxtime);
  2407.         test_flush;
  2408.       } 
  2409.       ptr=lien_tot;
  2410.     } else if (exit_xh) {  // sortir
  2411.       if (opt.errlog) {
  2412.         fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  2413.         test_flush;
  2414.       } 
  2415.       ptr=lien_tot;
  2416.     }
  2417.   } while(ptr<lien_tot);
  2418.   //
  2419.   //
  2420.   //
  2421.  
  2422.  
  2423.  
  2424.   // purger!
  2425.   if (opt.delete_old) {
  2426.     if (cache.lst) {
  2427.       FILE *old_lst,*new_lst;
  2428.       //
  2429. #if HTS_ANALYSTE==2
  2430.       _hts_in_html_parsing=3;
  2431. #endif
  2432.       //
  2433.       fclose(cache.lst); cache.lst=NULL;
  2434.       old_lst=fopen(fconcat(opt.path_log,"hts-cache/old.lst"),"rb");
  2435.       if (old_lst) {
  2436.         LLint sz=fsize(fconcat(opt.path_log,"hts-cache/new.lst"));
  2437.         new_lst=fopen(fconcat(opt.path_log,"hts-cache/new.lst"),"rb");
  2438.         if ((new_lst) && (sz>0)) {
  2439.           char* adr=(char*) malloct((INTsys)sz);
  2440.           if (adr) {
  2441.             if ((int) fread(adr,1,(INTsys)sz,new_lst) == sz) {
  2442.               char line[1100];
  2443.               int purge=0;
  2444.               while(!feof(old_lst)) {
  2445.                 linput(old_lst,line,1000);
  2446.                 if (!strstr(adr,line)) {    // fichier non trouvΘ dans le nouveau?
  2447.                   char file[HTS_URLMAXSIZE*2];
  2448.                   strcpy(file,opt.path_html);
  2449.                   strcat(file,line+1);
  2450.                   file[strlen(file)-1]='\0';
  2451.                   if (fexist(file)) {       // toujours sur disque: virer
  2452.                     if (opt.log) {
  2453.                       fspc(opt.log,"info"); fprintf(opt.log,"Purging %s"LF,file);
  2454.                     }
  2455.                     remove(file); purge=1;
  2456.                   }
  2457.                 }
  2458.               }
  2459.               {
  2460.                 fseek(old_lst,0,SEEK_SET);
  2461.                 while(!feof(old_lst)) {
  2462.                   linput(old_lst,line,1000);
  2463.                   while(strnotempty(line) && (line[strlen(line)-1]!='/') && (line[strlen(line)-1]!='\\')) {
  2464.                     line[strlen(line)-1]='\0';
  2465.                   }
  2466.                   if (strnotempty(line))
  2467.                     line[strlen(line)-1]='\0';
  2468.                   if (strnotempty(line))
  2469.                     if (!strstr(adr,line)) {    // non trouvΘ?
  2470.                       char file[HTS_URLMAXSIZE*2];
  2471.                       strcpy(file,opt.path_html);
  2472.                       strcat(file,line+1);
  2473.                       while ((strnotempty(file)) && (rmdir(file)==0)) {    // ok, ΘliminΘ (existait)
  2474.                         purge=1;
  2475.                         if (opt.log) {
  2476.                           fspc(opt.log,"info"); fprintf(opt.log,"Purging directory %s/"LF,file);
  2477.                           while(strnotempty(file) && (file[strlen(file)-1]!='/') && (file[strlen(file)-1]!='\\')) {
  2478.                             file[strlen(file)-1]='\0';
  2479.                           }
  2480.                           if (strnotempty(file))
  2481.                             file[strlen(file)-1]='\0';
  2482.                         }
  2483.                       }
  2484.                     }
  2485.                 }
  2486.               }
  2487.               //
  2488.               if (!purge) {
  2489.                 if (opt.log) {
  2490.                   fprintf(opt.log,"No files purged"LF);
  2491.                 }
  2492.               }
  2493.             }
  2494.             freet(adr);
  2495.           }
  2496.           fclose(new_lst);
  2497.         }
  2498.         fclose(old_lst);
  2499.       }
  2500.       //
  2501. #if HTS_ANALYSTE==2
  2502.       _hts_in_html_parsing=0;
  2503. #endif
  2504.     }
  2505.   }
  2506.   // fin purge!
  2507.   
  2508.   // afficher rΘsumΘ dans log
  2509.   if (opt.log!=NULL) {
  2510.     int error   = fspc(NULL,"error");
  2511.     int warning = fspc(NULL,"warning");
  2512.     int info    = fspc(NULL,"info");
  2513.     char htstime[256];
  2514.     // int n=(int) (stat_loaded/(time_local()-stat_timestart));
  2515.     int n=(int) (new_stat_bytes/(time_local()-stat_timestart));
  2516.     sec2str(htstime,time_local()-stat_timestart);
  2517.     //fprintf(opt.log,LF"HTS-mirror complete in %s : %d links scanned, %d files written (%d bytes overall) [%d bytes received at %d bytes/sec]"LF,htstime,lien_tot-1,stat_files,stat_bytes,stat_loaded,n);
  2518.     fprintf(opt.log,LF"HTTrack mirror complete in %s : %d links scanned, %d files written (%d bytes overall) [%d bytes received at %d bytes/sec]"LF,htstime,(int)lien_tot-1,(int)stat_files,(int)stat_bytes,(int)new_stat_bytes,(int)n);
  2519.     if (error)
  2520.       fprintf(opt.log,"(%d errors, %d warnings, %d messages)"LF,error,warning,info);
  2521.     else
  2522.       fprintf(opt.log,"(No errors, %d warnings, %d messages)"LF,warning,info);
  2523.     test_flush;
  2524.   }
  2525. #if DEBUG_HASH
  2526.   // noter les collisions
  2527.   {
  2528.     int i;
  2529.     int empty1=0,empty2=0,empty3=0;
  2530.     for(i=0;i<HTS_HASH_SIZE;i++) {
  2531.       if (hash.hash[0][i] == -1)
  2532.         empty1++;
  2533.       if (hash.hash[1][i] == -1)
  2534.         empty2++;
  2535.       if (hash.hash[2][i] == -1)
  2536.         empty3++;
  2537.     }
  2538.     printf("\n");
  2539.     printf("Debug info: Hash-table report\n");
  2540.     printf("Number of files entered:   %d\n",hashnumber);
  2541.     printf("Table size:                %d\n",HTS_HASH_SIZE);
  2542.     printf("\n");
  2543.     printf("Longest chain sav:              %d, empty: %d\n",longest_hash[0],empty1);
  2544.     printf("Longest chain adr,fil:          %d, empty: %d\n",longest_hash[1],empty2);
  2545.     printf("Longest chain former_adr/fil:   %d, empty: %d\n",longest_hash[2],empty3);
  2546.     printf("\n");
  2547.   }
  2548. #endif    
  2549.   // fin afficher rΘsumΘ dans log
  2550.   
  2551.   // dΘsallocation mΘmoire & buffers  
  2552.   XH_uninit    
  2553.  
  2554.   return 1;    // OK
  2555. }
  2556. // version 2 pour le reste
  2557. // flusher si on doit lire peu α peu le fichier
  2558. #undef test_flush
  2559. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  2560.  
  2561.  
  2562. // bannir host (trop lent etc)
  2563. void host_ban(httrackp* opt,lien_url** liens,int ptr,int lien_tot,lien_back* back,int back_max,char** filters,int filter_max,int* filptr,char* host) {
  2564.   //register int l;
  2565.   register int i;
  2566.  
  2567.   if (host[0]=='!')
  2568.     return;    // erreur.. dΘja cancellΘ.. bizzard.. devrait pas arriver
  2569.  
  2570.   // interdire host
  2571.   if (*filptr < filter_max) {
  2572.     strcpy(filters[*filptr],"-");
  2573.     strcat(filters[*filptr],host);
  2574.     strcat(filters[*filptr],"/*");     // host/ * interdit
  2575.     (*filptr)++; *filptr=minimum(*filptr,filter_max);  
  2576.   }
  2577.   
  2578.   // oups
  2579.   if (strlen(host)<=1) {    // euhh?? longueur <= 1
  2580.     if (strcmp(host,"file://")) {
  2581.       //## if (host[0]!=lOCAL_CHAR) {  // pas local
  2582.       if (opt->log!=NULL) {
  2583.         fprintf(opt->log,"PANIC! HostCancel detected memory leaks [char %d]"LF,host[0]); test_flush;
  2584.       }          
  2585.       return;  // purΘe
  2586.     }
  2587.   }
  2588.   
  2589.   // couper connexion
  2590.   for(i=0;i<back_max;i++) {
  2591.     if (back[i].status>=0)    // rΘception OU prΩt
  2592.       if (strfield2(back[i].url_adr,host)) {
  2593. #if HTS_DEBUG_CLOSESOCK
  2594.         DEBUG_W("host control: deletehttp\n");
  2595. #endif
  2596.         back[i].status=0;  // terminΘ
  2597.         if (back[i].r.soc!=INVALID_SOCKET) deletehttp(&back[i].r);
  2598.         back[i].r.soc=INVALID_SOCKET;
  2599.         back[i].r.statuscode=-2;    // timeout (peu importe si c'est un traffic jam)
  2600.         strcpy(back[i].r.msg,"Link Cancelled by host control");
  2601.         
  2602.         if ((opt->debug>1) && (opt->log!=NULL)) {
  2603.           fprintf(opt->log,"Shutdown: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  2604.         }          
  2605.       }
  2606.   }
  2607.   
  2608.   // effacer liens
  2609.   //l=strlen(host);
  2610.   for(i=0;i<lien_tot;i++) {
  2611.     //if (liens[i]->adr_len==l) {    // mΩme taille de chaεne
  2612.     // Calcul de taille sΘcurisΘe
  2613.     if (liens[i]) {
  2614.       if (liens[i]->adr) {
  2615.         int l = 0;
  2616.         while((liens[i]->adr[l]) && (l<1020)) l++;
  2617.         if ((l > 0) && (l<1020)) {   // sΘcuritΘ
  2618.           if (strfield2(jump_identification(liens[i]->adr),host)) {    // host
  2619.             if ((opt->debug>1) && (opt->log!=NULL)) {
  2620.               fprintf(opt->log,"Cancel: %s%s"LF,liens[i]->adr,liens[i]->fil); test_flush;
  2621.             }
  2622.             strcpy(liens[i]->adr,"!");    // cancel (invalide hash)
  2623. #if HTS_HASH
  2624. #else
  2625.             liens[i]->sav_len=-1;         // taille invalide
  2626. #endif
  2627.             // on efface pas le hash, because si on rencontre le lien, reverif sav..
  2628.           }
  2629.         } else {
  2630.           if (opt->log!=NULL) {
  2631.             char dmp[1040];
  2632.             dmp[0]='\0';
  2633.             strncat(dmp,liens[i]->adr,1024);
  2634.             fprintf(opt->log,"WARNING! HostCancel detected memory leaks [len %d at %d]"LF,l,i); test_flush;
  2635.             fprintf(opt->log,"dump 1024 bytes (address %d): "LF"%s"LF,(int)liens[i]->adr,dmp); test_flush;
  2636.           }          
  2637.         }
  2638.       } else {
  2639.         if (opt->log!=NULL) {
  2640.           fprintf(opt->log,"WARNING! HostCancel detected memory leaks [adr at %d]"LF,i); test_flush;
  2641.         }  
  2642.       }
  2643.     } else {
  2644.       if (opt->log!=NULL) {
  2645.         fprintf(opt->log,"WARNING! HostCancel detected memory leaks [null at %d]"LF,i); test_flush;
  2646.       }  
  2647.     }
  2648.     //}
  2649.   }
  2650. }
  2651.  
  2652.  
  2653.  
  2654.  
  2655.  
  2656.  
  2657. // vΘrifier prΘsence de l'arbo
  2658. int structcheck(char* s) {
  2659.   // vΘrifier la prΘsence des dossier(s)
  2660.   char *a=s;
  2661.   char nom[HTS_URLMAXSIZE*2];
  2662.   char *b;
  2663.  
  2664.   if (strnotempty(s)==0) return 0;
  2665.   if (strlen(s)>HTS_URLMAXSIZE) return 0;
  2666.  
  2667.   if (structcheck_buff==NULL) {
  2668.     structcheck_buff=(char*) malloct(65536);  // ** ** non dΘsallouΘ
  2669.     strcpy(structcheck_buff,"#");
  2670.   } else if (strlen(structcheck_buff)>65000) {
  2671.     strcpy(structcheck_buff,"#");  // rΘinit.. c'est idiot ** **
  2672.   }
  2673.   
  2674.   if (structcheck_buff) {
  2675.     b=nom;
  2676.     do {    
  2677.       if (*a) *b++=*a++;
  2678.       while((*a!='/') && (*a!='\0')) *b++=*a++;
  2679.       *b='\0';    // pas de ++ pour boucler
  2680.       if (*a=='/') {    // toujours dossier
  2681.         if (strnotempty(nom)) {
  2682.           char tempo[HTS_URLMAXSIZE*2];
  2683.           
  2684.           strcpy(tempo,"#"); strcat(tempo,nom); strcat(tempo,"#");
  2685.           if (strstr(structcheck_buff,tempo)==NULL) {    // non encore crΘΘ
  2686.             strcat(structcheck_buff,"#"); strcat(structcheck_buff,nom); strcat(structcheck_buff,"#");  // ajouter α la liste
  2687.                         
  2688. #if HTS_WIN
  2689.             if (mkdir(fconv(nom))!=0)
  2690. #else    
  2691.               if (mkdir(fconv(nom),HTS_ACCESS_FOLDER)!=0)
  2692. #endif
  2693.               {
  2694. #if HTS_REMOVE_ANNOYING_INDEX
  2695.                 // might be a filename with same name than this folder
  2696.                 // then, remove it to allow folder creation
  2697.                 // it happends when servers gives a folder index while
  2698.                 // requesting / page
  2699.                 // -> if the file can be opened (not a folder) then rename it
  2700.                 FILE* fp=fopen(fconv(nom),"ab");
  2701.                 if (fp) {
  2702.                   fclose(fp);
  2703.                   rename(fconv(nom),fconcat(fconv(nom),".txt"));
  2704.                 }
  2705.                 // if it fails, that's too bad
  2706. #if HTS_WIN
  2707.                 mkdir(fconv(nom));
  2708. #else    
  2709.                 mkdir(fconv(nom),HTS_ACCESS_FOLDER);
  2710. #endif
  2711. #endif
  2712.                 // Si existe dΘja renvoie une erreur.. tant pis
  2713.               }
  2714. #if HTS_WIN==0
  2715.               chmod(fconv(nom),HTS_ACCESS_FOLDER);
  2716. #endif
  2717.           }
  2718.         }
  2719.         *b++=*a++;    // slash
  2720.       } 
  2721.     } while(*a);
  2722.   }
  2723.   return 0;
  2724. }
  2725.  
  2726.  
  2727. // sauver un fichier
  2728. int filesave(char* adr,int len,char* s) {
  2729.   FILE* fp;
  2730.   // Θcrire le fichier
  2731.   if ((fp=filecreate(s))!=NULL) {
  2732.     int nl=0;
  2733.     if (len>0) {
  2734.       nl=(int) fwrite(adr,1,len,fp);
  2735.     }
  2736.     fclose(fp);
  2737.     usercommand(0,NULL,antislash(s));
  2738.     if (nl!=len)  // erreur
  2739.       return -1;
  2740.   } else
  2741.     return -1;
  2742.   
  2743.   return 0;
  2744. }
  2745.  
  2746.  
  2747. // ouvrir un fichier (avec chemin Un*x)
  2748. FILE* filecreate(char* s) {
  2749.   char fname[HTS_URLMAXSIZE*2];
  2750.   FILE* fp;
  2751.   fname[0]='\0';
  2752.  
  2753.   // noter lst
  2754.   filenote(s,NULL);
  2755.   
  2756.   // if (*s=='/') strcpy(fname,s+1); else strcpy(fname,s);    // pas de / (root!!) // ** SIIIIIII!!! α cause de -O <path>
  2757.   strcpy(fname,s);
  2758.  
  2759. #if HTS_DOSNAME
  2760.   // remplacer / par des slash arriΦre
  2761.   {
  2762.     int i=0;
  2763.     while(fname[i]) {
  2764.       if (fname[i]=='/')
  2765.         fname[i]='\\';
  2766.       i++;
  2767.     } 
  2768.   } 
  2769.   // a partir d'ici le slash devient antislash
  2770. #endif
  2771.   
  2772.   // construite le chemin si besoin est
  2773.   if (structcheck(s)!=0) {
  2774.     return NULL;
  2775.   }
  2776.   
  2777.   
  2778.   // ouvrir
  2779.   fp=fopen(fname,"wb");
  2780. #if HTS_WIN==0
  2781.   if (fp!=NULL) chmod(fname,HTS_ACCESS_FILE);
  2782. #endif
  2783.   return fp;
  2784. }
  2785.  
  2786. // noter fichier
  2787. int filenote(char* s,filecreate_params* params) {
  2788. //int filenote(char* s,char* params) {
  2789.   static FILE* lst = NULL;
  2790.   static char path[HTS_URLMAXSIZE*2]="";
  2791.   
  2792.   // gestion du fichier liste liste
  2793.   if (params) {
  2794.     //filecreate_params* p = (filecreate_params*) params;
  2795.     strcpy(path,params->path);
  2796.     lst=params->lst;
  2797.     return 0;
  2798.   } else if (lst) {
  2799.     char savelst[HTS_URLMAXSIZE*2];
  2800.     strcpy(savelst,fslash(s));
  2801.     // couper chemin?
  2802.     if (strnotempty(path)) {
  2803.       if (strncmp(fslash(path),savelst,strlen(path))==0) {  // couper
  2804.         strcpy(savelst,s+strlen(path));
  2805.       }
  2806.     }
  2807.     fprintf(lst,"[%s]"LF,savelst);
  2808.     fflush(lst);
  2809.   }
  2810.   return 1;
  2811. }
  2812.  
  2813. // executer commande utilisateur
  2814. HTS_INLINE void usercommand(int _exe,char* _cmd,char* file) {
  2815.   static int exe=0;
  2816.   static char cmd[2048]="";
  2817.   if (_exe) {
  2818.     strcpy(cmd,_cmd);
  2819.     if (strnotempty(cmd))
  2820.       exe=_exe;
  2821.     else
  2822.       exe=0;
  2823.   }
  2824.   if (exe) {
  2825.     if (strnotempty(file)) {
  2826.       if (strnotempty(cmd)) {
  2827.         usercommand_exe(cmd,file);
  2828.       }
  2829.     }
  2830.   }
  2831. }
  2832. void usercommand_exe(char* cmd,char* file) {
  2833.   char temp[8192];
  2834.   char c[2]="";
  2835.   int i;
  2836.   temp[0]='\0';
  2837.   //
  2838.   for(i=0;i<(int) strlen(cmd);i++) {
  2839.     if ((cmd[i]=='$') && (cmd[i+1]=='0')) {
  2840.       strcat(temp,file);
  2841.       i++;
  2842.     } else {
  2843.       c[0]=cmd[i]; c[1]='\0';
  2844.       strcat(temp,c);
  2845.     }
  2846.   }
  2847.   system(temp);
  2848. }
  2849.  
  2850. // Θcrire n espaces dans fp
  2851. HTS_INLINE int fspc(FILE* fp,char* type) {
  2852.   static int error=0,warning=0,info=0;
  2853.   //
  2854.   if (fp) {
  2855.     char s[256];
  2856.     time_t tt;
  2857.     struct tm* A;
  2858.     tt=time(NULL);
  2859.     A=localtime(&tt);
  2860.     strftime(s,250,"%H:%M:%S",A);
  2861.     if (strnotempty(type))
  2862.       fprintf(fp,"%s\t%c%s: \t",s,hichar(*type),type+1);
  2863.     else
  2864.       fprintf(fp,"%s\t \t",s);
  2865.     if (strcmp(type,"warning")==0)
  2866.       warning++;
  2867.     else if (strcmp(type,"error")==0)
  2868.       error++;
  2869.     else if (strcmp(type,"info")==0)
  2870.       info++;
  2871.   } 
  2872.   else if (strcmp(type,"warning")==0)
  2873.     return warning;
  2874.   else if (strcmp(type,"error")==0)
  2875.     return error;
  2876.   else if (strcmp(type,"info")==0)
  2877.     return info;
  2878.   return 0;
  2879. }
  2880.  
  2881.  
  2882. // vΘrifier taux de transfert
  2883. void check_rate(double stat_timestart,int maxrate) {
  2884.   // vΘrifier taux de transfert (pas trop grand?)
  2885.   if (maxrate>0) {
  2886.     int r = (int) (new_stat_bytes/(time_local()-stat_timestart));    // taux actuel de transfert
  2887.     HTS_TOTAL_RECV_STATE=0;
  2888.     if (r>maxrate) {    // taux>taux autorisΘ
  2889.       int taux = (int) (((double) (r - maxrate) * 100) / (double) maxrate);
  2890.       if (taux<15)
  2891.         HTS_TOTAL_RECV_STATE=1;   // ralentir un peu (<15% dΘpassement)
  2892.       else if (taux<50)
  2893.         HTS_TOTAL_RECV_STATE=2;   // beaucoup (<50% dΘpassement)
  2894.       else
  2895.         HTS_TOTAL_RECV_STATE=3;   // ΘnormΘment (>50% dΘpassement)
  2896.     }
  2897.   }
  2898. }
  2899.  
  2900.  
  2901. // ---
  2902. // sous routines liΘes au moteur et au backing
  2903.  
  2904. // remplir backing si moins de max_bytes en mΘmoire
  2905. HTS_INLINE int back_fillmax(lien_back* back,int back_max,httrackp* opt,cache_back* cache,lien_url** liens,int ptr,int numero_passe,int lien_tot) {
  2906.   if (back_incache(back,back_max)<opt->maxcache) {  // pas trop en mΘmoire?
  2907.     return back_fill(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  2908.   }
  2909.   return -1;                /* plus de place */
  2910. }
  2911.  
  2912. // remplir backing
  2913. int back_fill(lien_back* back,int back_max,httrackp* opt,cache_back* cache,lien_url** liens,int ptr,int numero_passe,int lien_tot) {
  2914.   int n;
  2915.  
  2916.   // ajouter autant de socket qu'on peut ajouter
  2917.   n=opt->maxsoc-back_nsoc(back,back_max);
  2918.  
  2919.   // vΘrifier qu'il restera assez de place pour les tests ensuite (en thΘorie, 1 entrΘe libre restante suffirait)
  2920.   n=min( n, back_available(back,back_max) - 8 );
  2921.  
  2922.   if (n>0) {
  2923.     int p;
  2924.  
  2925.     if (ptr<cache->ptr_last) {      /* restart (2 scans: first html, then non html) */
  2926.       cache->ptr_ant=0;
  2927.     }
  2928.  
  2929.     p=ptr+1;
  2930.     /* on a dΘja parcouru */
  2931.     if (p<cache->ptr_ant)
  2932.       p=cache->ptr_ant;
  2933.     while((p<lien_tot) && (n>0) && (p < ptr+opt->maxcache_anticipate)) {
  2934.       int ok=1;
  2935.       
  2936.       // on ne met pas le fichier en backing si il doit Ωtre traitΘ aprΦs
  2937.       if (liens[p]->pass2) {  // 2Φ passe
  2938.         if (numero_passe!=1)
  2939.           ok=0;
  2940.       } else {
  2941.         if (numero_passe!=0)
  2942.           ok=0;
  2943.       }
  2944.       
  2945.       // note: si un backing est fini, il reste en mΘmoire jusqu'α ce que
  2946.       // le ptr l'atteigne
  2947.       if (ok) {
  2948.         if (!back_exist(back,back_max,liens[p]->adr,liens[p]->fil,liens[p]->sav)) {
  2949.           if (back_add(back,back_max,opt,cache,liens[p]->adr,liens[p]->fil,liens[p]->sav,liens[liens[p]->precedent]->adr,liens[liens[p]->precedent]->fil,liens[p]->testmode)==-1) {
  2950.             if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  2951.               fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: unable to add more links through back_add for back_fill"LF);
  2952.               test_flush;
  2953.             }                    
  2954. #if BDEBUG==1
  2955.             printf("error while adding\n");
  2956. #endif                  
  2957.             n=0;    // sortir
  2958.           } else {
  2959.             n--;
  2960. #if BDEBUG==1
  2961.             printf("backing: %s%s\n",liens[p]->adr,liens[p]->fil);          
  2962. #endif
  2963.           } 
  2964.         }
  2965.       }
  2966.       p++;
  2967.     }  // while
  2968.     /* sauver position derniΦre anticipation */
  2969.     cache->ptr_ant=p;
  2970.     cache->ptr_last=ptr;
  2971.   }
  2972.   return 0;
  2973. }
  2974. // ---
  2975.  
  2976.  
  2977.  
  2978.  
  2979.  
  2980.  
  2981.  
  2982.  
  2983.  
  2984.  
  2985.  
  2986.  
  2987.  
  2988.  
  2989.  
  2990.  
  2991.  
  2992.  
  2993. // routines de dΘtournement de SIGHUP & co (Unix)
  2994. void sig_finish( int code ) {       // finir et quitter
  2995.   signal(code,sig_term);  // quitter si encore
  2996.   exit_xh=1;
  2997.   printf("\nExit requested to engine (signal %d)\n",code);
  2998. }
  2999. void sig_term( int code ) {       // quitter brutalement
  3000.   printf("\nProgram terminated (signal %d)\n",code);
  3001.   exit(0);
  3002. }
  3003. #if HTS_WIN
  3004. void sig_ask( int code ) {        // demander
  3005.   static char s[256];
  3006.   signal(code,sig_term);  // quitter si encore
  3007.   printf("\nQuit program/Cancel? (Q/C) ");
  3008.   fflush(stdout);
  3009.   scanf("%s",s);
  3010.   if ( (s[0]=='y') || (s[0]=='Y') || (s[0]=='o') || (s[0]=='O') || (s[0]=='q') || (s[0]=='Q'))
  3011.     exit(0);     // quitter
  3012.   signal(code,sig_ask);  // remettre signal
  3013. }
  3014. #else
  3015. void sig_back( int code ) {       // ignorer et mettre en backing 
  3016.   signal(code,sig_ignore);
  3017.   sig_doback(0);
  3018. }
  3019. void sig_ask( int code ) {        // demander
  3020.   static char s[256];
  3021.   signal(code,sig_term);  // quitter si encore
  3022.   printf("\nQuit program/Background/bLind background/Cancel? (Q/B/L/C) ");
  3023.   fflush(stdout);
  3024.   scanf("%s",s);
  3025.   if ( (s[0]=='y') || (s[0]=='Y') || (s[0]=='o') || (s[0]=='O') || (s[0]=='q') || (s[0]=='Q'))
  3026.     exit(0);     // quitter
  3027.   else if ( (s[0]=='b') || (s[0]=='B') || (s[0]=='a') || (s[0]=='A') )
  3028.     sig_doback(0);  // arriΦre plan
  3029.   else if ( (s[0]=='l') || (s[0]=='L') )
  3030.     sig_doback(1);  // arriΦre plan
  3031.   else {
  3032.     printf("cancel..\n");
  3033.     signal(code,sig_ask);  // remettre signal
  3034.   }
  3035. }
  3036. void sig_ignore( int code ) {     // ignorer signal
  3037.   // // signal(code,sig_ignore);
  3038. }
  3039. void sig_doback(int blind) {       // mettre en backing 
  3040.   int out=-1;
  3041.   //
  3042.   printf("\nMoving to background to complete the mirror...\n"); fflush(stdout);
  3043.   if (!blind)
  3044.     out = open("hts-nohup.out",O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR);
  3045.   if (out == -1)
  3046.     out = open("/dev/null",O_WRONLY,S_IRUSR|S_IWUSR);
  3047.   close(0);
  3048.   close(1);
  3049.   dup(out);
  3050.   close(2);
  3051.   dup(out);
  3052.   //
  3053.   switch (fork()) {
  3054.   case 0: 
  3055.     break;
  3056.   case -1:
  3057.     printf("Error: can not fork process\n");
  3058.     break;
  3059.   default:            // pere
  3060.     usleep(100000);   // pause 1/10s "A  microsecond  is  .000001s"
  3061.     _exit(0);
  3062.     break;  
  3063.   }
  3064. }
  3065. #endif
  3066. // fin routines de dΘtournement de SIGHUP & co
  3067.  
  3068. // Poll stdin.. si besoin
  3069. #if HTS_POLL
  3070. // lecture stdin des caractΦres disponibles
  3071. int read_stdin(char* s,int max) {
  3072.   int i=0;
  3073.   while((check_stdin()) && (i<(max-1)) )
  3074.     s[i++]=fgetc(stdin);
  3075.   s[i]='\0';
  3076.   return i;
  3077. }
  3078. #ifdef _WIN32
  3079. HTS_INLINE int check_stdin() {
  3080.   return (_kbhit());
  3081. }
  3082. #else
  3083. HTS_INLINE int check_flot(T_SOC s) {
  3084.   fd_set fds;
  3085.   struct timeval tv;
  3086.   FD_ZERO(&fds);
  3087.   FD_SET((T_SOC) s,&fds);
  3088.   tv.tv_sec=0;
  3089.   tv.tv_usec=0;
  3090.   select(s+1,&fds,NULL,NULL,&tv);
  3091.   return FD_ISSET(s,&fds);
  3092. }
  3093. HTS_INLINE int check_stdin() {
  3094.   fflush(stdout); fflush(stdin);
  3095.   if (check_flot(0))
  3096.     return 1;
  3097.   return 0;
  3098. }
  3099. #endif
  3100. #endif
  3101.  
  3102.  
  3103. // Attente de touche
  3104. #if HTS_ANALYSTE!=2
  3105. int ask_continue() {
  3106.   char s[12]="";
  3107.   printf("Press <Y><Enter> to confirm, <N><Enter> to abort\n");
  3108.   io_flush; linput(stdin,s,4);
  3109.   if (strnotempty(s)) {
  3110.     if ((strfield2(s,"N")) || (strfield2(s,"NO")) || (strfield2(s,"NON")))
  3111.       return 0;
  3112.   }
  3113.   return 1;
  3114. }
  3115. #else
  3116. int ask_continue() {
  3117.   char* s;
  3118.   s=hts_htmlcheck_query2(HTbuff);
  3119.   if (s) {
  3120.     if (strnotempty(s)) {
  3121.       if ((strfield2(s,"N")) || (strfield2(s,"NO")) || (strfield2(s,"NON")))
  3122.         return 0;
  3123.     }
  3124.     return 1;
  3125.   }
  3126.   return 1;
  3127. }
  3128. #endif
  3129.  
  3130. // nombre de digits dans un nombre
  3131. int nombre_digit(int n) {
  3132.   register int i=1;
  3133.   while(n >= 10) { n/=10; i++; }
  3134.   return i;
  3135. }
  3136.  
  3137.  
  3138. // renvoi adresse de la fin du token dans p
  3139. // renvoi NULL si la chaine est un token unique
  3140. // (PATCHE Θgalement la chaine)
  3141. // ex: "test" "test2" renvoi adresse sur espace
  3142. // flag==1 si chaine comporte des echappements comme \"
  3143. char* next_token(char* p,int flag) {
  3144.   int detect=0;
  3145.   int quote=0;
  3146.   p--;
  3147.   do {
  3148.     p++;
  3149.     if (flag && (*p=='\\')) {   // sauter \x ou \"
  3150.       if (quote) {
  3151.         char c='\0';
  3152.         if (*(p+1)=='\\')
  3153.           c='\\';
  3154.         else if (*(p+1)=='"')
  3155.           c='"';
  3156.         if (c) {
  3157.           char tempo[8192];
  3158.           tempo[0]=c; tempo[1]='\0';
  3159.           strcat(tempo,p+2);
  3160.           strcpy(p,tempo);
  3161.         }
  3162.       }
  3163.     }
  3164.     else if (*p==34) {  // guillemets (de fin)
  3165.       quote=!quote;
  3166.     }
  3167.     else if (*p==32) {
  3168.       if (!quote)
  3169.         detect=1;
  3170.     }
  3171.     else if (*p=='\0') {
  3172.       p=NULL;
  3173.       detect=1;
  3174.     }
  3175.   } while(!detect);
  3176.   return p;
  3177. }
  3178.  
  3179. // routines annexes 
  3180. #if HTS_ANALYSTE==2
  3181. // canceller un fichier (noter comme cancellable)
  3182. char* hts_cancel_file(char * s) {
  3183.   static char sav[HTS_URLMAXSIZE*2]="";
  3184.   if (s[0]!='\0')
  3185.   if (sav[0]=='\0')
  3186.     strcpy(sav,s);
  3187.   return sav;
  3188. }
  3189. void hts_cancel_test() {
  3190.   if (_hts_in_html_parsing==2)
  3191.     _hts_cancel=2;
  3192. }
  3193. void hts_cancel_parsing() {
  3194.   if (_hts_in_html_parsing)
  3195.    _hts_cancel=1;
  3196. }
  3197. #endif
  3198. //        for(_i=0;(_i<back_max) && (index<NFICH);_i++) {
  3199. //          i=(back_index+_i)%back_max;    // commencer par le "premier" (l'actuel)
  3200. //          if (back[i].status>=0) {     // signifie "lien actif"
  3201.  
  3202.  
  3203. /*  
  3204. hts_add_file, add/get elements in the add chain for java parsing
  3205. if file_position >= 0
  3206.   push 'file/file_position'
  3207.   return 1 (return 0 if exists)
  3208. else
  3209.   pop file -> 'file'
  3210.   return 'file_position'
  3211. else if empty/error
  3212.   return -1;
  3213. */
  3214. typedef struct addfile_chain {
  3215.   char name[1024];
  3216.   int pos;
  3217.   struct addfile_chain* next;
  3218. } addfile_chain;
  3219. int hts_add_file(char* file,int file_position) {
  3220.   static struct addfile_chain* chain=NULL;
  3221.  
  3222.   if (file_position>=0) {         /* copy file to the chain */
  3223.     struct addfile_chain** current;
  3224.     current=&chain;                     /* start from */
  3225.     while(*current) {
  3226.       if (strcmp((*current)->name,file)==0)
  3227.         return 0;                       /* already exists */
  3228.       current=&( (*current)->next );    /* 'next' address */
  3229.     }
  3230.     *current=calloc(1,sizeof(addfile_chain));
  3231.     if (*current) {
  3232.       (*current)->next=NULL;
  3233.       (*current)->pos=-1;
  3234.       (*current)->name[0]='\0';
  3235.     }
  3236.     if (*current) {
  3237.       strcpy((*current)->name,file);
  3238.       (*current)->pos=file_position;
  3239.       return 1;
  3240.     } else {
  3241.       printf("PANIC! Too many Java files during parsing [1]\n");
  3242.       return -1;
  3243.     }
  3244.   } else {                      /* copy last element in file and delete it */
  3245.     if (file)
  3246.       file[0]='\0';
  3247.     if (chain) {
  3248.       struct addfile_chain** current;
  3249.       int pos=-1;
  3250.       current=&chain;                     /* start from */
  3251.       while( (*current)->next ) {
  3252.         current=&( (*current)->next );    /* 'next' address */
  3253.       }
  3254.       if (file)
  3255.         strcpy(file,(*current)->name);
  3256.       pos=(*current)->pos;
  3257.       free(*current);
  3258.       *current=NULL;
  3259.       return pos;
  3260.     }
  3261.     return -1;                            /* no more elements */
  3262.   }
  3263.  
  3264.     /*
  3265.   static char* buffer;
  3266.   if (strlen(file)==8) {
  3267.     if (file[0]=='$') { // commande
  3268.       if (strcmp(file,"$BUFFER$")==0) {  // indiquer adresse buffer!
  3269.         buffer=file;    // le buffer
  3270.         buffer[0]='\0';
  3271.         return 1;
  3272.       }
  3273.     }
  3274.   }
  3275.   
  3276.   if (strlen(buffer)<32000) {   // vΘrifier..
  3277.     strcat(buffer,file);
  3278.     strcat(buffer,"&");  // sΘparateur
  3279.   } else {
  3280.     printf("PANIC! Too many Java files during parsing [1]\n");  // **
  3281.     buffer[32000]='\0';    // couper
  3282.   }
  3283.   */
  3284.  
  3285.   return 0;
  3286. }
  3287.  
  3288. #if HTS_ANALYSTE==2
  3289. // en train de parser un fichier html? rΘponse: % effectuΘs
  3290. // flag>0 : refresh demandΘ
  3291. int hts_is_parsing(int flag) {
  3292.   if (_hts_in_html_parsing) {  // parsing?
  3293.     if (flag>=0) _hts_in_html_poll=1;  // faudrait un tit refresh
  3294.     return max(_hts_in_html_done,1); // % effectuΘs
  3295.   } else {
  3296.     return 0;                 // non
  3297.   }
  3298. }
  3299. int hts_is_testing() {            // 0 non 1 test 2 purge
  3300.   if (_hts_in_html_parsing==2)
  3301.     return 1;
  3302.   else if (_hts_in_html_parsing==3)
  3303.     return 2;
  3304.   return 0;
  3305. }
  3306. // message d'erreur?
  3307. char* hts_errmsg() {
  3308.   return _hts_errmsg;
  3309. }
  3310. // mode pause transfer
  3311. int hts_setpause(int p) {
  3312.   if (p>=0) _hts_setpause=p;
  3313.   return _hts_setpause;
  3314. }
  3315. // rΘgler en cours de route les paramΦtres rΘglables..
  3316. // -1 : erreur
  3317. int hts_setopt(httrackp* opt) {
  3318.   if (opt) _hts_setopt=opt;
  3319.   return 0;
  3320. }
  3321. // ajout d'URL
  3322. // -1 : erreur
  3323. int hts_addurl(char** url) {
  3324.   if (url) _hts_addurl=url;
  3325.   return (_hts_addurl!=NULL);
  3326. }
  3327. int hts_resetaddurl() {
  3328.   _hts_addurl=NULL;
  3329.   return (_hts_addurl!=NULL);
  3330. }
  3331. // copier nouveaux paramΦtres si besoin
  3332. int copy_htsopt(httrackp* from,httrackp* to) {
  3333.   if (from->maxsite > -1) 
  3334.     to->maxsite = from->maxsite;
  3335.   
  3336.   if (from->maxfile_nonhtml > -1) 
  3337.     to->maxfile_nonhtml = from->maxfile_nonhtml;
  3338.   
  3339.   if (from->maxfile_html > -1) 
  3340.     to->maxfile_html = from->maxfile_html;
  3341.   
  3342.   if (from->maxsoc > 0) 
  3343.     to->maxsoc = from->maxsoc;
  3344.   
  3345.   if (from->nearlink > -1) 
  3346.     to->nearlink = from->nearlink;
  3347.   
  3348.   if (from->timeout > -1) 
  3349.     to->timeout = from->timeout;
  3350.   
  3351.   if (from->rateout > -1)
  3352.     to->rateout = from->rateout;
  3353.   
  3354.   if (from->maxtime > -1) 
  3355.     to->maxtime = from->maxtime;
  3356.   
  3357.   if (from->maxrate > -1)
  3358.     to->maxrate = from->maxrate;
  3359.   
  3360.   if (strnotempty(from->user_agent)) 
  3361.     strcpy(to->user_agent , from->user_agent);
  3362.   
  3363.   if (from->retry > -1) 
  3364.     to->retry = from->retry;
  3365.   
  3366.   if (from->hostcontrol > -1) 
  3367.     to->hostcontrol = from->hostcontrol;
  3368.   
  3369.   if (from->errpage > -1) 
  3370.     to->errpage = from->errpage;
  3371.  
  3372.   if (from->parseall > -1) 
  3373.     to->parseall = from->parseall;
  3374.  
  3375.  
  3376.   // test all: bit 8 de travel
  3377.   if (from->travel > -1)  {
  3378.     if (from->travel & 256)
  3379.       to->travel|=256;
  3380.     else
  3381.       to->travel&=255;
  3382.   }
  3383.  
  3384.  
  3385.   return 0;
  3386. }
  3387.  
  3388. #endif
  3389. //
  3390.  
  3391. // message copyright interne
  3392. void voidf(void) {
  3393.   char* a;
  3394.   a=""CRLF""CRLF;
  3395.   a="+-----------------------------------------------+"CRLF;
  3396.   a="|HyperTextTRACKer, Offline Browser Utility      |"CRLF;
  3397.   a="|                      HTTrack Website Copier   |"CRLF;
  3398.   a="|Code:       Windows Interface Xavier Roche     |"CRLF;
  3399.   a="|              Motif Interface Yann Philippot   |"CRLF;
  3400.   a="|                  HTS/HTTrack Xavier Roche     |"CRLF;
  3401.   a="|                  Java Parser Yann Philippot   |"CRLF;
  3402.   a="|                                               |"CRLF;
  3403.   a="|Tested on:                 Windows95,98,NT,2K  |"CRLF;
  3404.   a="|                           Linux PC            |"CRLF;
  3405.   a="|                           Sun-Solaris 5.6     |"CRLF;
  3406.   a="|                           AIX 4               |"CRLF;
  3407.   a="|                                               |"CRLF;
  3408.   a="|(C)1998-2001 X.R.,Y.P.                         |"CRLF;
  3409.   a="|  Brought to you by Serianet, Caen, France     |"CRLF;
  3410.   a="|                                               |"CRLF;
  3411.   a="|Use this program at your own risks!            |"CRLF;    
  3412.   a="+-----------------------------------------------+"CRLF;
  3413.   a=""CRLF;
  3414. }
  3415.  
  3416.  
  3417. // HTTrack Website Copier Copyright (C) Xavier Roche, Yann Philippot
  3418. //
  3419.  
  3420.