home *** CD-ROM | disk | FTP | other *** search
/ PC Open 48 / pcopen48.iso / Internet / HtTrack / DATA1.CAB / Sources / src / htsparse.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-21  |  87.1 KB  |  1,864 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. /* DIRECT INCLUDE TO httrack.c                                  */
  38. /* Author: Xavier Roche                                         */
  39. /* ------------------------------------------------------------ */
  40.  
  41.  
  42. #if HTS_ANALYSTE
  43. if (hts_htmlcheck(r.adr,(int)r.size,urladr,urlfil)) {
  44. #endif          
  45.   FILE* fp=NULL;      // fichier Θcrit localement                                               // et si level>0
  46.   char* adr=r.adr;    // pointeur (on parcourt)
  47.   char* lastsaved;    // adresse du dernier octet sauvΘ + 1
  48.   if ( (opt.debug>1) && (opt.log!=NULL) ) {
  49.     fspc(opt.log,"debug"); fprintf(opt.log,"scan file.."LF); test_flush;
  50.   }
  51.   
  52.   if ((opt.getmode & 1) && (ptr>0)) {  // rΘcupΘrer les html sur disque       
  53.     // crΘer le fichier html local
  54.     HT_ADD_FOP;   // Θcrire peu α peu le fichier
  55.   }
  56.   
  57.   if (!error) {
  58.     int detect_title=0;  // dΘtection  du title
  59.     //
  60.     int intag=0;         // on est dans un tag
  61.     int incomment=0;     // dans un <!--
  62.     int inscript=0;      // dans un scipt pour applets javascript)
  63.     int inscript_tag=0;  // on est dans un <body onLoad="... terminΘ par >
  64.     char inscript_tag_lastc='\0';  
  65.                            // terminaison (" ou ') du "<body onLoad=.."
  66.     int inscriptgen=0;     // on est dans un code gΘnΘrant, ex aprΦs obj.write("..
  67.     char scriptgen_q='\0'; // caractΦre faisant office de guillemet (' ou ")
  68.     int nofollow=0;        // ne pas scanner
  69.     //
  70.     int parseall_lastc='\0';    // dernier caractΦre parsΘ pour parseall
  71.     int parseall_incomment=0;   // dans un /* */ (exemple: a = /* URL */ "img.gif";)
  72.     //
  73.     char* intag_start=adr;
  74.     int intag_start_valid=0;
  75.     HT_ADD_START;    // dΘbuter
  76.  
  77.  
  78.     /* statistics */
  79.     if ((opt.getmode & 1) && (ptr>0)) { 
  80.       stat_files++;
  81.       stat_bytes+=r.size;
  82.     }
  83.  
  84.  
  85.     /* Check is the file is a .js file */
  86.     if (strfield2(r.contenttype,"application/x-javascript")!=0) {      /* JavaScript js file */
  87.       inscript=1;
  88.       intag=1;     // because aprΦs <script> on y est .. - pas utile
  89.       intag_start_valid=0;    // OUI car nous sommes dans du code, plus dans du "vrai" tag
  90.       if ((opt.debug>1) && (opt.log!=NULL)) {
  91.         fspc(opt.log,"debug"); fprintf(opt.log,"note: this file is a javascript file"LF); test_flush;
  92.       }
  93.     }
  94.     
  95.     
  96.  
  97.     // ------------------------------------------------------------
  98.     // analyser ce qu'il y a en mΘmoire (fichier html)
  99.     // on scanne les balises
  100.     // ------------------------------------------------------------
  101. #if HTS_ANALYSTE==2
  102.     _hts_in_html_done=0;     // 0% scannΘs
  103.     _hts_cancel=0;           // pas de cancel
  104.     _hts_in_html_parsing=1;  // flag pour indiquer un parsing
  105. #endif
  106.     base[0]='\0';    // effacer base-href
  107.     lastsaved=adr;
  108.     do {
  109.       int p=0;
  110.       error=0;
  111.       
  112.       //if (nofollow)       // ne pas scanner
  113.       //  nofollow=nofollow;    // pipo!!!
  114.       // drapeau: vΘrifier que l'on est dans un tag
  115.       /*else*/
  116.       if ((*adr=='<') && (!inscript) && (!incomment)) { 
  117.         intag=1;
  118.         parseall_incomment=0;
  119.         //inquote=0;  // effacer quote
  120.         intag_start=adr; intag_start_valid=1;
  121.         codebase[0]='\0';    // effacer Θventuel codebase
  122.         
  123.         if (opt.getmode & 1) {  // sauver html
  124.           p=strfield(adr,"</html");
  125.           if (p==0) p=strfield(adr,"<head>");
  126.           if (p) {
  127.             if (strnotempty(opt.footer)) {
  128.               char tempo[1024+HTS_URLMAXSIZE*2];
  129.               char gmttime[256];
  130.               tempo[0]='\0';
  131.               time_gmt_rfc822(gmttime);
  132.               strcpy(tempo,CRLF);
  133.               sprintf(tempo+strlen(tempo),opt.footer,jump_identification(urladr),urlfil,gmttime,"","","","","");
  134.               strcat(tempo,CRLF);
  135.               //fwrite(tempo,1,strlen(tempo),fp);
  136.               HT_ADD(tempo);
  137.             }
  138.           }
  139.         }        
  140.         
  141.         // Θliminer les <!-- (commentaires) : intag dΘvalidΘ
  142.         if (*(adr+1)=='!')
  143.           if (*(adr+2)=='-')
  144.             if (*(adr+3)=='-') {
  145.               intag=0;
  146.               incomment=1;
  147.               intag_start_valid=0;
  148.             }
  149.             
  150.       }
  151.       else if ((*adr=='>') && ( (!inscript) || (inscript_tag) ) ) {
  152.         if (inscript_tag) {
  153.           inscript_tag=inscript=0;
  154.           intag=0;
  155.           incomment=0;
  156.           intag_start_valid=0;
  157.         } else if (!incomment) {
  158.           intag=0; //inquote=0;
  159.           
  160.           // entrΘe dans du javascript?
  161.           // on parse ICI car il se peut qu'on ait eu a parser les src=.. dedans
  162.           //if (!inscript) {  // sinon on est dans un obj.write("..
  163.           if ((intag_start_valid) && check_tag(intag_start,"script")) {
  164.             char* a=intag_start;    // <
  165.             // ** while(is_realspace(*(--a)));
  166.             if (*a=='<') {  // s√r que c'est un tag?
  167.               inscript=1;
  168.               intag=1;     // because aprΦs <script> on y est .. - pas utile
  169.               intag_start_valid=0;    // OUI car nous sommes dans du code, plus dans du "vrai" tag
  170.             }
  171.           }
  172.         } else {     // sortie de commentaire?
  173.           // vΘrifier fermeture correcte
  174.           if ( (*(adr-1)=='-') && (*(adr-2)=='-') ) {
  175.             intag=0;
  176.             incomment=0;
  177.             intag_start_valid=0;
  178.           }
  179. #if GT_ENDS_COMMENT
  180.           /* wrong comment ending */
  181.           else {
  182.             /* check if correct ending do not exist 
  183.                <!-- foo > example <!-- bar > is sometimes accepted by browsers
  184.                when no --> is used somewhere else.. darn those browsers are dirty
  185.             */
  186.             if (!strstr(adr,"-->")) {
  187.               intag=0;
  188.               incomment=0;
  189.               intag_start_valid=0;
  190.             }
  191.           }
  192. #endif
  193.         }
  194.         //}
  195.       }
  196.       //else if (*adr==34) {
  197.       //  inquote=(inquote?0:1);
  198.       //}
  199.       else if (intag || inscript) {    // nous sommes dans un tag/commentaire, tester si on recoit un tag
  200.         int p_type=0;
  201.         int p_nocatch=0;
  202.         int p_searchMETAURL=0;  // chercher ..URL=<url>
  203.         int add_class=0;        // ajouter .class
  204.         char* p_flush=NULL;
  205.         
  206.         
  207.         // ------------------------------------------------------------
  208.         // parsing ΘvolΘ
  209.         // ------------------------------------------------------------
  210.         if (((isalpha((unsigned char)*adr)) || (*adr=='/') || (inscript) || (inscriptgen))) {  // sinon pas la peine de tester..
  211.  
  212.  
  213.           /* caractΦre de terminaison pour "miniparsing" javascript=.. ? 
  214.              (ex: <a href="javascript:()" action="foo"> ) */
  215.           if (inscript_tag) {
  216.             if (inscript_tag_lastc) {
  217.               if (*adr == inscript_tag_lastc) {
  218.                 /* sortir */
  219.                 inscript_tag=inscript=0;
  220.                 incomment=0;
  221.               }
  222.             }
  223.           }
  224.  
  225.           // Construction index.html (sommaire)
  226.           // Avant de tester les a href,
  227.           // Ici on teste si l'on doit construire l'index vers le(s) site(s) miroir(s)
  228.           if (opt.makeindex && (ptr>0)) {
  229.             if (opt.getmode & 1) {  // autorisation d'Θcrire
  230.               if (!makeindex_done) {  // autoriation d'Θcrire un index
  231.                 if (level1==level) {    // on note toujours les premiers liens
  232.                   if (!detect_title) {
  233.                     p=strfield(adr,"title");  
  234.                     if (p) {
  235.                       if (*(adr-1)=='/') p=0;    // /title
  236.                     } else {
  237.                       if (strfield(adr,"/html"))
  238.                         p=-1;                    // noter, mais sans titre
  239.                       else if (strfield(adr,"body"))
  240.                         p=-1;                    // noter, mais sans titre
  241.                     }
  242.                   } else
  243.                     p=0;
  244.                   
  245.                   if (p) {    // ok center                            
  246.                     if (makeindex_fp==NULL) {
  247.                       verif_backblue(opt.path_html);    // gΘnΘrer gif
  248.                       makeindex_fp=filecreate(fconcat(opt.path_html,"index.html"));
  249.                       if (makeindex_fp!=NULL) {
  250.                         fprintf(makeindex_fp,"<HTML>"CRLF);
  251.                         fprintf(makeindex_fp,"<!-- Mirror and index made by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  252.                         fprintf(makeindex_fp,"<HEAD>"CRLF"<TITLE>");
  253.                         fprintf(makeindex_fp,"Local index");
  254.                         fprintf(makeindex_fp,"</TITLE>"CRLF"</HEAD>"CRLF"<BODY BACKGROUND=\"backblue.gif\"><H1 ALIGN=Center>");
  255.                         fprintf(makeindex_fp,"<U>Index of locally available sites:</U>");
  256.                         fprintf(makeindex_fp,"</H1>"CRLF"<BR>"CRLF"<BR><BR>"CRLF"<UL>"CRLF);
  257.                       } else makeindex_done=-1;    // fait, erreur
  258.                     }
  259.                     
  260.                     if (makeindex_fp!=NULL) {
  261.                       char tempo[HTS_URLMAXSIZE*2];
  262.                       char s[HTS_URLMAXSIZE*2];
  263.                       char* a=NULL;
  264.                       char* b=NULL;
  265.                       s[0]='\0';
  266.                       if (p>0) {
  267.                         a=strchr(adr,'>');
  268.                         if (a!=NULL) {
  269.                           a++;
  270.                           while(is_space(*a)) a++;    // sauter espaces & co
  271.                           b=strchr(a,'<');   // prochain tag
  272.                         }
  273.                       }
  274.                       if (lienrelatif(tempo,liens[ptr]->sav,concat(opt.path_html,"index.html"))==0) {
  275.                         detect_title=1;      // ok dΘtectΘ pour cette page!
  276.                         //
  277.                         fprintf(makeindex_fp,"<LI>"CRLF);
  278.                         if ((b==a) || (a==NULL) || (b==NULL)) {    // pas de titre
  279.                           fprintf(makeindex_fp,"<A HREF=\"%s\">%s</A><BR>"CRLF,tempo,tempo);
  280.                         } else if ((b-a)<256) {
  281.                           b--;
  282.                           while(is_space(*b)) b--;
  283.                           strncpy(s,a,b-a+1);
  284.                           *(s+(b-a)+1)='\0';
  285.                           fprintf(makeindex_fp,"<A HREF=\"%s\">%s</A><BR>"CRLF,tempo,s);
  286.                         }
  287.                         fprintf(makeindex_fp,"</LI>"CRLF);
  288.                       }
  289.                     }
  290.                   }
  291.                   
  292.                 } else if (level<level1) {   // on a sautΘ level1+1 et level1
  293.                   if (makeindex_fp) {
  294.                     fprintf(makeindex_fp,"</UL>"CRLF"<BR>"CRLF"<BR>"CRLF"<BR>"CRLF"</BODY>"CRLF);
  295.                     fprintf(makeindex_fp,"<I><H6 ALIGN=\"RIGHT\">Mirror and index made by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS"</H6></I>"CRLF);
  296.                     fprintf(makeindex_fp,"<!-- Mirror and index made by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"CRLF);
  297.                     fprintf(makeindex_fp,"<!-- Thanks for using HTTrack Website Copier! -->"CRLF);
  298.                     fprintf(makeindex_fp,"</HTML>"CRLF);
  299.                     fflush(makeindex_fp);
  300.                     fclose(makeindex_fp);  // α ne pas oublier sinon on passe une nuit blanche
  301.                     makeindex_fp=NULL;
  302.                     usercommand(0,NULL,fconcat(opt.path_html,"index.html"));                            
  303.                   }
  304.                   makeindex_done=1;    // ok c'est fait
  305.                 }
  306.               }
  307.             }
  308.           } // if (opt.makeindex)
  309.           // FIN Construction index.html (sommaire)
  310.  
  311.           
  312.           // Note:
  313.           // Certaines pages ne respectent pas le html
  314.           // notamment les guillements ne sont pas fixΘs
  315.           // Nous sommes dans un tag, donc on peut faire un test plus
  316.           // large pour pouvoi prendre en compte ces particularitΘs
  317.           
  318.           // α vΘrifier: ACTION, CODEBASE, VRML
  319.           
  320.           if (ptr>0) {        /* pas premiΦre page 0 (primary) */
  321.             p=0;  // saut pour le nom de fichier: adresse nom fichier=adr+p
  322.             
  323.             // ------------------------------
  324.             // dΘtection d'Θcriture JavaScript.
  325.             // osons les obj.write et les obj.href=.. ! osons!
  326.             // note: inscript==1 donc on sautera aprΦs les \"
  327.             if (inscript) {
  328.               if (inscriptgen) {          // on est dΘja dans un objet gΘnΘrant..
  329.                 if (*adr==scriptgen_q) {  // fermeture des " ou '
  330.                   if (*(adr-1)!='\\') {   // non
  331.                     inscriptgen=0;        // ok parsing terminΘ
  332.                   }
  333.                 }
  334.               } else {
  335.                 char* a=NULL;
  336.                 char check_this_fking_line=0;  // parsing code javascript..
  337.                 char must_be_terminated=0;     // caractΦre obligatoire de terminaison!
  338.                 int token_size;
  339.                 if (!(token_size=strfield(adr,".writeln"))) // dΘtection ...objet.write[ln]("code html")...
  340.                   token_size=strfield(adr,".write");
  341.                 if (token_size) {
  342.                   a=adr+token_size;
  343.                   while(is_realspace(*a)) a++; // sauter espaces
  344.                   if (*a=='(') {  // dΘbut parenthΦse
  345.                     check_this_fking_line=2;  // α parser!
  346.                     must_be_terminated=')';
  347.                     a++;  // sauter (
  348.                   }
  349.                 }
  350.                 // euhh ??? ???
  351.                 /* else if (strfield(adr,".href")) {  // dΘtection ...objet.href="...
  352.                 a=adr+5;
  353.                 while(is_realspace(*a)) a++; // sauter espaces
  354.                 if (*a=='=') {  // ohh un Θgal
  355.                 check_this_fking_line=1;  // α noter!
  356.                 must_be_terminated=';';   // et si t'as oubliΘ le ; tu sais pas coder
  357.                 a++;   // sauter =
  358.                 }
  359.                 
  360.               }*/
  361.                 
  362.                 // on a un truc du genre instruction"code gΘnΘrΘ" dont on parse le code
  363.                 if (check_this_fking_line) {
  364.                   while(is_realspace(*a)) a++;
  365.                   if ((*a=='\'') || (*a=='"')) {  // dΘpart de '' ou ""
  366.                     char *b;
  367.                     int ex=0;
  368.                     scriptgen_q=*a;    // quote
  369.                     b=a+1;      // dΘpart de la chaεne
  370.                     // vΘrifier forme ("code") et pas ("code"+var), ingΘrable
  371.                     do {
  372.                       a++;  // caractΦre suivant
  373.                       if (*a==scriptgen_q) if (*(a-1)!='\\')  // quote non slash
  374.                         ex=1;            // sortie
  375.                       if ((*a==10) || (*a==13))
  376.                         ex=1;
  377.                     } while(!ex);
  378.                     if (*a==scriptgen_q) {  // fin du quote
  379.                       a++;
  380.                       while(is_realspace(*a)) a++;
  381.                       if (*a==must_be_terminated) {  // parenthΦse fermante: ("..")
  382.                         
  383.                         // bon, on doit parser une ligne javascript
  384.                         // 1) si check.. ==1 alors c'est un nom de fichier direct, donc
  385.                         // on fixe p sur le saut nΘcessaire pour atteindre le nom du fichier
  386.                         // et le moteur se dΘbrouillera ensuite tout seul comme un grand
  387.                         // 2) si check==2 c'est un peu plus tordu car lα on gΘnΘre du
  388.                         // code html au sein de code javascript au sein de code html
  389.                         // dans ce cas on doit fixer un flag α un puis ensuite dans la boucle
  390.                         // on devra parser les instructions standard comme <a href etc
  391.                         // NOTE: le code javascript autogΘnΘrΘ n'est pas pris en compte!!
  392.                         // (et ne marche pas dans 50% des cas de toute facon!)
  393.                         if (check_this_fking_line==1) {
  394.                           p=(int) b-(int) adr;  // calculer saut!
  395.                         } else {
  396.                           inscriptgen=1;        // SCRIPTGEN actif
  397.                           adr=b;                // jump
  398.                         }
  399.                         
  400.                         if ((opt.debug>1) && (opt.log!=NULL)) {
  401.                           char str[512];
  402.                           str[0]='\0';
  403.                           strncat(str,b,minimum((int) a-(int) b+1,32));
  404.                           fspc(opt.log,"debug"); fprintf(opt.log,"active code (%s) detected in javascript: %s"LF,(check_this_fking_line==2)?"parse":"pickup",str); test_flush;
  405.                         }
  406.                       }
  407.                       
  408.                     }
  409.                     
  410.                   }
  411.                   
  412.                   
  413.                 }
  414.               }
  415.             }
  416.             // fin detection code gΘnΘrant javascript vers html
  417.             // ------------------------------
  418.             
  419.             
  420.             // analyse proprement dite, A HREF=.. etc..
  421.             if (!p) {
  422.               // si dans un tag, et pas dans un script - sauf si on analyse un obj.write("..
  423.               if ((intag && (!inscript)) || inscriptgen) {
  424.                 if ( (*(adr-1)=='<') || (is_space(*(adr-1))) ) {   // <tag < tag etc
  425.                   // <A HREF=.. pour les liens HTML
  426.                   p=rech_tageq(adr,"href");
  427.                   if (p) {    // href.. tester si c'est une bas href!
  428.                     if ((intag_start_valid) && check_tag(intag_start,"base")) {  // oui!
  429.                       // ** note: base href et codebase ne font pas bon mΘnage..
  430.                       p_type=2;    // c'est un chemin
  431.                     }
  432.                   }
  433.                   
  434.                   /* Tags supplΘmentaires α vΘrifier (<img src=..> etc) */
  435.                   if (p==0) {
  436.                     int i=0;
  437.                     while( (p==0) && (strnotempty(hts_detect[i])) ) {
  438.                       p=rech_tageq(adr,hts_detect[i]);
  439.                       i++;
  440.                     }
  441.                   }
  442.  
  443.                   /* Tags supplΘmentaires α vΘrifier : URL=.. */
  444.                   if (p==0) {
  445.                     int i=0;
  446.                     while( (p==0) && (strnotempty(hts_detectURL[i])) ) {
  447.                       p=rech_tageq(adr,hts_detectURL[i]);
  448.                       i++;
  449.                     }
  450.                     if (p)
  451.                       p_searchMETAURL=1;
  452.                   }
  453.  
  454.                   /* Tags supplΘmentaires α vΘrifier, mais α ne pas capturer */
  455.                   if (p==0) {
  456.                     int i=0;
  457.                     while( (p==0) && (strnotempty(hts_detectandleave[i])) ) {
  458.                       p=rech_tageq(adr,hts_detectandleave[i]);
  459.                       i++;
  460.                     }
  461.                     if (p)
  462.                       p_nocatch=1;      /* ne pas rechercher */
  463.                   }
  464.  
  465.                   /* EvΘnements */
  466.                   if (p==0) {
  467.                     int i=0;
  468.                     /* dΘtection onLoad etc */
  469.                     while( (p==0) && (strnotempty(hts_detect_js[i])) ) {
  470.                       p=rech_tageq(adr,hts_detect_js[i]);
  471.                       i++;
  472.                     }
  473.                     /* non dΘtectΘ - dΘtecter Θgalement les onXxxxx= */
  474.                     if (p==0) {
  475.                       if ( (*adr=='o') && (*(adr+1)=='n') && isUpperLetter(*(adr+2)) ) {
  476.                         p=0;
  477.                         while(isalpha((unsigned char)adr[p]) && (p<64) ) p++;
  478.                         if (p<64) {
  479.                           while(is_space(adr[p])) p++;
  480.                           if (adr[p]=='=')
  481.                             p++;
  482.                           else p=0;
  483.                         } else p=0;
  484.                       }
  485.                     }
  486.                     /* OK, ΘvΘnement repΘrΘ */
  487.                     if (p) {
  488.                       inscript_tag_lastc=*(adr+p-1);     /* α attendre α la fin */
  489.                       adr+=p;     /* saut */
  490.                                   /*
  491.                                   On est dΘsormais dans du code javascript
  492.                       */
  493.                       inscript_tag=inscript=1;
  494.                     }
  495.                     p=0;        /* quoi qu'il arrive, ne rien dΘmarrer ici */
  496.                   }
  497.  
  498.                   // <APPLET CODE=.. pour les applet java.. [CODEBASE (chemin..) α faire]
  499.                   if (p==0) {
  500.                     p=rech_tageq(adr,"code");
  501.                     if (p) {
  502.                       if ((intag_start_valid) && check_tag(intag_start,"applet")) {  // dans un <applet !
  503.                         p_type=-1;  // juste le nom de fichier+dossier, Θcire avant codebase 
  504.                         add_class=1;   // ajouter .class au besoin                         
  505.                         
  506.                         // vΘrifier qu'il n'y a pas de codebase APRES
  507.                         // sinon on swappe les deux.
  508.                         // pas trΦs propre mais c'est ce qu'il y a de plus simple α faire!!
  509.                         
  510.                         {
  511.                           char *a;
  512.                           a=adr;
  513.                           while((*a) && (*a!='>') && (!rech_tageq(a,"codebase"))) a++;
  514.                           if (rech_tageq(a,"codebase")) {  // banzai! codebase=
  515.                             char* b;
  516.                             b=strchr(a,'>');
  517.                             if (b) {
  518.                               if (((int) b - (int) adr) < 1000) {    // au total < 1Ko
  519.                                 char tempo[HTS_URLMAXSIZE*2];
  520.                                 tempo[0]='\0';
  521.                                 strncat(tempo,a,(int) b - (int) a);
  522.                                 strcat( tempo," ");
  523.                                 strncat(tempo,adr,(int) a - (int) adr - 1);
  524.                                 // Θventuellement remplire par des espaces pour avoir juste la taille
  525.                                 while((int) strlen(tempo)<((int) b - (int) adr))
  526.                                   strcat(tempo," ");
  527.                                 // pas d'erreur?
  528.                                 if ((int) strlen(tempo) == ((int) b - (int) adr)) {
  529.                                   strncpy(adr,tempo,strlen(tempo));   // PAS d'octet nul α la fin!
  530.                                   p=0;    // DEVALIDER!!
  531.                                   p_type=0;
  532.                                   add_class=0;
  533.                                 }
  534.                               }
  535.                             }
  536.                           }
  537.                         }
  538.                         
  539.                       }
  540.                     }
  541.                   }
  542.                   
  543.                   // liens α patcher mais pas α charger (ex: codebase)
  544.                   if (p==0) {  // note: si non chargΘ (ex: ignorer .class) patchΘ tout de mΩme
  545.                     p=rech_tageq(adr,"codebase");
  546.                     if (p) {
  547.                       if ((intag_start_valid) && check_tag(intag_start,"applet")) {  // dans un <applet !
  548.                         p_type=-2;
  549.                       } else p=-1;   // ne plus chercher
  550.                     }
  551.                   }
  552.                   
  553.                   
  554.                   // Meta tags pour robots
  555.                   if (p==0) {
  556.                     if (opt.robots) {
  557.                       if ((intag_start_valid) && check_tag(intag_start,"meta")) {
  558.                         if (rech_tageq(adr,"name")) {    // name=robots.txt
  559.                           char tempo[1100];
  560.                           char* a;
  561.                           tempo[0]='\0';
  562.                           a=strchr(adr,'>');
  563. #if DEBUG_ROBOTS
  564.                           printf("robots.txt meta tag detected\n");
  565. #endif
  566.                           if (a) {
  567.                             if (((int) a - (int) adr) < 999 ) {
  568.                               strncat(tempo,adr,(int) a - (int) adr);
  569.                               if (strstrcase(tempo,"content")) {
  570.                                 if (strstrcase(tempo,"robots")) {
  571.                                   if (strstrcase(tempo,"nofollow")) {
  572. #if DEBUG_ROBOTS
  573.                                     printf("robots.txt meta tag: nofollow in %s%s\n",urladr,urlfil);
  574. #endif
  575.                                     nofollow=1;       // NE PLUS suivre liens dans cette page
  576.                                     if (opt.errlog) {
  577.                                       fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Link %s%s not scanned (follow robots meta tag)"LF,urladr,urlfil);
  578.                                       test_flush;
  579.                                     }
  580.                                   }
  581.                                 }
  582.                               }
  583.                             }
  584.                           }
  585.                         }
  586.                       }
  587.                     }
  588.                   }
  589.                   
  590.                   // entrΘe dans une applet javascript
  591.                   /*if (!inscript) {  // sinon on est dans un obj.write("..
  592.                   if (p==0)
  593.                   if (rech_sampletag(adr,"script"))
  594.                   if (check_tag(intag_start,"script")) {
  595.                   inscript=1;
  596.                   }
  597.                         }*/
  598.                   
  599.                   // Ici on procΦde α une analyse du code javascript pour tenter de rΘcupΘrer
  600.                   // certains fichiers Θvidents.
  601.                   // C'est devenu obligatoire vu le nombre de pages qui intΦgrent
  602.                   // des images rΘactives par exemple
  603.                 }
  604.               } else if (inscript) {
  605.                 if (strfield(adr,"/script") ) {
  606.                   char* a=adr;
  607.                   //while(is_realspace(*(--a)));
  608.                   while( is_realspace(*a) ) a--;
  609.                   a--;
  610.                   if (*a=='<') {  // s√r que c'est un tag?
  611.                     inscript=0;
  612.                   }
  613.                 } else {
  614.                   int nc;
  615.                   char  expected     = '=';          // caractΦre attendu aprΦs
  616.                   char* expected_end = ";";
  617.                   if (inscript_tag)
  618.                     expected_end=";\"\'";            // voir a href="javascript:doc.location='foo'"
  619.                   nc = strfield(adr,".src");  // nom.src="image";
  620.                   if (!nc) nc = strfield(adr,".location");  // document.location="doc"
  621.                   if (!nc) nc = strfield(adr,".href");  // document.location="doc"
  622.                   if (!nc) if ( (nc = strfield(adr,".open")) ) { // window.open("doc",..
  623.                     expected='(';    // parenthΦse
  624.                     expected_end="),";  // fin: virgule ou parenthΦse
  625.                   }
  626.                   if (!nc) if ( (nc = strfield(adr,".replace")) ) { // window.replace("url")
  627.                     expected='(';    // parenthΦse
  628.                     expected_end=")";  // fin: parenthΦse
  629.                   }
  630.                   if (!nc) if ( (nc = strfield(adr,".link")) ) { // window.link("url")
  631.                     expected='(';    // parenthΦse
  632.                     expected_end=")";  // fin: parenthΦse
  633.                   }
  634.                   if (nc) {
  635.                     char *a;
  636.                     a=adr+nc;
  637.                     while(is_space(*a)) a++;
  638.                     if (*a == expected) {
  639.                       a++;
  640.                       while(is_realspace(*a)) a++;
  641.                       if ((*a==34) || (*a=='\'')) {
  642.                         char *b,*c;
  643.                         a++;
  644.                         b=a;
  645.                         while((*b!=34) && (*b!='\'') && (*b!='\0')) b++;
  646.                         c=b--; c++;
  647.                         while(*c==' ') c++;
  648.                         if ((strchr(expected_end,*c)) || (*c=='\n') || (*c=='\r')) {
  649.                           c-=2;
  650.                           if ((int) c-(int) a+1) {
  651.                             if ((opt.debug>1) && (opt.log!=NULL)) {
  652.                               char str[512];
  653.                               str[0]='\0';
  654.                               strncat(str,a,minimum((int) c-(int) a+1,32));
  655.                               fspc(opt.log,"debug"); fprintf(opt.log,"link detected in javascript: %s"LF,str); test_flush;
  656.                             }
  657.                             p=(int) a- (int) adr;    // p non nul: TRAITER CHAINE COMME FICHIER
  658.                           }
  659.                         }
  660.                         
  661.                         
  662.                       }
  663.                     }
  664.                   }
  665.                   
  666.                 }
  667.               }
  668.             }
  669.                 
  670.           } else
  671.             p=rech_tageq(adr,"primary");    // lien primaire, yeah
  672.           }
  673.           
  674.           
  675.           // ------------------------------------------------------------
  676.           // dernier recours - parsing "sale" : dΘtection systΘmatique des .gif, etc.
  677.           // risque: gΘnΘrer de faux fichiers parazites
  678.           // fix: ne parse plus dans les commentaires
  679.           // ------------------------------------------------------------
  680.           if ( (opt.parseall) && (ptr>0)) {           // option parsing "brut"
  681.             int incomment_justquit=0;
  682.             if (!is_realspace(*adr)) {
  683.               int noparse=0;
  684.  
  685.               // Gestion des /* */
  686.               if (inscript) {
  687.                 if (parseall_incomment) {
  688.                   if ((*adr=='/') && (*(adr-1)=='*'))
  689.                     parseall_incomment=0;
  690.                   incomment_justquit=1;       // ne pas noter dernier caractΦre
  691.                 } else {
  692.                   if ((*adr=='/') && (*(adr+1)=='*'))
  693.                     parseall_incomment=1;
  694.                 }
  695.               } else
  696.                 parseall_incomment=0;
  697.  
  698.               /* vΘrifier que l'on est pas dans un <!-- --> pur */
  699.               if ( (!intag) && (incomment) && (!inscript))
  700.                 noparse=1;        /* commentaire */
  701.  
  702.               // recherche d'URLs
  703.               if ((!parseall_incomment) && (!noparse)) {
  704.                 if (!p) {                   // non dΘja trouvΘ
  705.                   if (adr != r.adr) {     // >1 caractΦre
  706.                     // scanner les chaines
  707.                     if ((*adr == '\"') || (*adr=='\'')) {         // "xx.gif" 'xx.gif'
  708.                       if (strchr("=(,",parseall_lastc)) {    // exemple: a="img.gif..
  709.                         char *a=adr;
  710.                         char stop=*adr;  // " ou '
  711.                         int count=0;
  712.                         
  713.                         // sauter caractΦres
  714.                         a++;
  715.                         while((*a) && (*a!='\'') && (*a!='\"') && (count<HTS_URLMAXSIZE)) { count++; a++; }
  716.                         
  717.                         // ok chaine terminΘe par " ou '
  718.                         if ((*a == stop) && (count<HTS_URLMAXSIZE) && (count>0)) {
  719.                           char c;
  720.                           char* aend;
  721.                           //
  722.                           aend=a;     // sauver dΘbut
  723.                           a++;
  724.                           while(is_realspace(*a)) a++;
  725.                           c=*a;
  726.                           if (strchr("),;>/+",c)) {     // exemple: ..img.gif";
  727.                             // le / est pour funct("img.gif" /* URL */);
  728.                             char tempo[HTS_URLMAXSIZE*2];
  729.                             char type[256];
  730.                             int url_ok=0;      // url valide?
  731.                             tempo[0]='\0'; type[0]='\0';
  732.                             //
  733.                             strncat(tempo,adr+1,count);
  734.                             //
  735.                             if ((!strchr(tempo,' ')) || inscript) {   // espace dedans: mΘfiance! (sauf dans code javascript)
  736.                               int invalid_url=0;
  737.                               
  738.                               // vΘrifier qu'il n'y a pas de caractΦres spΘciaux
  739.                               if (strchr(tempo,'*')
  740.                                 || strchr(tempo,'<')
  741.                                 || strchr(tempo,'>'))
  742.                                 invalid_url=1;
  743.                               
  744.                               /* non invalide? */
  745.                               if (!invalid_url) {
  746.                                 // Un plus α la fin? Alors ne pas prendre sauf si extension ("/toto.html#"+tag)
  747.                                 if (c!='+') {    // PAS de plus α la fin
  748.                                   char* a;
  749.                                   if ((strncmp(tempo,"http://",7)==0) || (strncmp(tempo,"ftp://",6)==0))  // ok pas de problΦme
  750.                                     url_ok=1;
  751.                                   else if (tempo[strlen(tempo)-1]=='/') {        // un slash: ok..
  752.                                     if (inscript)   // sinon si pas javascript, mΘfiance (rΘpertoire style base?)
  753.                                       url_ok=1;
  754.                                   } else if ((a=strchr(tempo,'/'))) {        // un slash: ok..
  755.                                     if (inscript) {    // sinon si pas javascript, mΘfiance (style "text/css")
  756.                                       if (strchr(a+1,'/'))  // un seul / : abandon (STYLE type='text/css')
  757.                                         url_ok=1;
  758.                                     }
  759.                                   }
  760.                                 }
  761.                                 // Prendre si extension reconnue
  762.                                 if (!url_ok) {
  763.                                   get_httptype(type,tempo,0);
  764.                                   if (strnotempty(type))     // type reconnu!
  765.                                     url_ok=1;
  766.                                 }
  767.                                 //
  768.                                 // Ok, cela pourrait Ωtre une URL
  769.                                 if (url_ok) {
  770.                                   // Accepter URL, on la traitera comme une URL normale!!
  771.                                   p=1;
  772.                                 }
  773.                               }
  774.                             }
  775.                           }
  776.                         }
  777.                       }
  778.                     }
  779.                   }
  780.                 }  // p == 0
  781.                 
  782.                 // plus dans un commentaire
  783.                 if (!incomment_justquit)
  784.                   parseall_lastc=*adr;             // caractΦre avant le prochain
  785.                 
  786.               } // not in comment
  787.               
  788.             }  // if realspace
  789.           }  // if parseall
  790.           
  791.           
  792.           // ------------------------------------------------------------
  793.           // p!=0 : on a repΘrΘ un Θventuel lien
  794.           // ------------------------------------------------------------
  795.           //
  796.           if (p>0) {    // on a repΘrΘ un lien
  797.             //int lien_valide=0;
  798.             char* eadr=NULL;          /* fin de l'URL */
  799.             char* quote_adr=NULL;     /* adresse du ? dans l'adresse */
  800.             int ok=1;
  801.             char quote='\0';
  802.  
  803.             // TEST
  804.             /*{
  805.               static int loop=0;
  806.               if ((++loop)%5000==0)
  807.                 loop=0;
  808.             }*/
  809.             
  810.             // si nofollow a ΘtΘ dΘclenchΘ, rΘΘcrire tous les liens en externe
  811.             if (nofollow)
  812.               p_nocatch=1;
  813.  
  814.             // Θcrire codebase avant, flusher avant code
  815.             if ((p_type==-1) || (p_type==-2)) {
  816.               if ((opt.getmode & 1) && (ptr>0)) {
  817.                 HT_ADD_ADR;    // refresh
  818.               }
  819.               lastsaved=adr;    // dernier Θcrit+1
  820.             }
  821.             
  822.             // sauter espaces
  823.             adr+=p;
  824.             while((is_space(*adr)) && (quote=='\0')) {
  825.               if (!quote)
  826.                 if ((*adr=='\"') || (*adr=='\''))
  827.                   quote=*adr;                     // on doit attendre cela α la fin
  828.                                                   // puis quitter
  829.                 adr++;    // sauter les espaces, "" et cie
  830.             }
  831.             /* s'arrΩter que ce soit un ' ou un " : pour document.write('<img src="foo'+a); par exemple! */
  832.             if (inscript)
  833.               quote='\0';
  834.             
  835.             // sauter Θventuel \" ou \' javascript
  836.             if (inscript) {    // on est dans un obj.write("..
  837.               if (*adr=='\\') {
  838.                 if ((*(adr+1)=='\'') || (*(adr+1)=='"')) {  // \" ou \'
  839.                   adr+=2;    // sauter
  840.                 }
  841.               }
  842.             }
  843.             
  844.             // sauter content="1;URL=http://..
  845.             if (p_searchMETAURL) {
  846.               int l=0;
  847.               while(!strfield(adr+l,"URL=") && (l<128) ) l++;
  848.               if (!strfield(adr,"URL="))
  849.                 ok=-1;
  850.               else
  851.                 adr+=(l+4);
  852.             }
  853.  
  854.             /* Θviter les javascript:document.location=.. : les parser, plut⌠t */
  855.             if (ok!=-1) {
  856.               if (strfield(adr,"javascript:")) {
  857.                 ok=-1;
  858.                 /*
  859.                 On est dΘsormais dans du code javascript
  860.                 */
  861.                 inscript_tag=inscript=1;
  862.                 inscript_tag_lastc=quote;     /* α attendre α la fin */
  863.               }
  864.             }
  865.             
  866.             if (p_type==1) {
  867.               if (*adr=='#') {
  868.                 adr++;           // sauter # pour usemap etc
  869.               }
  870.             }
  871.             eadr=adr;
  872.             
  873.             // ne pas flusher aprΦs code si on doit Θcrire le codebase avant!
  874.             if ((p_type!=-1) && (p_type!=2) && (p_type!=-2)) {
  875.               if ((opt.getmode & 1) && (ptr>0)) {
  876.                 HT_ADD_ADR;    // refresh
  877.               }
  878.               lastsaved=adr;    // dernier Θcrit+1
  879.               // aprΦs on Θcrira soit les donnΘes initiales,
  880.               // soir une URL/lien modifiΘ!
  881.             } else if (p_type==-1) p_flush=adr;    // flusher jusqu'α adr ensuite
  882.             
  883.             if (ok!=-1) {    // continuer
  884.               // dΘcouper le lien
  885.               do {
  886.                 if ((* (unsigned char*) eadr)<32) {   // caractΦre de contr⌠le (ou \0)
  887.                   if (!is_space(*eadr))
  888.                     ok=0; 
  889.                 }
  890.                 if ( ( ((int) eadr) - ((int) adr) ) > HTS_URLMAXSIZE)  // ** trop long, >HTS_URLMAXSIZE caractΦres (on prΘvoit HTS_URLMAXSIZE autres pour path)
  891.                   ok=-1;    // ne pas traiter ce lien
  892.                 
  893.                 if (ok) {
  894.                   //if (*eadr!=' ') {  
  895.                   if (is_space(*eadr)) {   // guillemets,CR, etc
  896.                     if ((!quote) || (*eadr==quote))     // si pas d'attente de quote spΘciale ou si quote atteinte
  897.                       ok=0; 
  898.                   }
  899.                   else {
  900.                     switch(*eadr) {
  901.                     case '>': 
  902.                       if (!quote) {
  903.                         if (!inscript) {
  904.                           intag=0;    // PLUS dans un tag!
  905.                           intag_start_valid=0;
  906.                         }
  907.                         ok=0;
  908.                       }
  909.                       break;
  910.                       /*case '<':*/ case '#': ok=0; break;    // case '?': non!
  911.                     case '\\': if (inscript) ok=0; break;     // \" ou \' point d'arrΩt
  912.                     case '?': quote_adr=adr; break;           // noter position query
  913.                     }
  914.                   }
  915.                   //}
  916.                 } 
  917.                 eadr++;
  918.               } while(ok==1);     
  919.               
  920.               if ( (((int) eadr)-((int) adr)) <= 1) ok=-1;     // lien vide
  921.             }
  922.             
  923.             if (ok==0) {    // tester un lien
  924.               char lien[HTS_URLMAXSIZE*2];
  925.               int meme_adresse=0;      // 0 par dΘfaut pour primary
  926.               //char *copie_de_adr=adr;
  927.               //char* p;
  928.               
  929.               // construire lien (dΘcoupage)
  930.               if ( (((int) eadr)-((int) adr)-1) < HTS_URLMAXSIZE  ) {    // pas trop long?
  931.                 strncpy(lien,adr,((int) eadr)-((int) adr)-1);
  932.                 *(lien+  (((int) eadr)-((int) adr))-1  )='\0';
  933.                 //printf("link: %s\n",lien);          
  934.                 // supprimer les espaces
  935.                 while((lien[strlen(lien)-1]==' ') && (strnotempty(lien))) lien[strlen(lien)-1]='\0';
  936.                 // supprimer les // en / (sauf pour http://)
  937.                 {
  938.                   char *a,*p,*q;
  939.                   int done=0;
  940.                   a=strstr(lien,":/");    // http://
  941.                   if (a) {
  942.                     a++;
  943.                     while(*a=='/') a++;    // position aprΦs http://
  944.                   } else {
  945.                     a=lien;                // dΘbut
  946.                   }
  947.                   q=strchr(a,'?');     // ne pas traiter aprΦs '?'
  948.                   if (!q)
  949.                     q=a+strlen(a)-1;
  950.                   while(( p=strstr(a,"//")) && (!done) ) {    // remplacer // par /
  951.                     if ((int) p>(int) q) {   // aprΦs le ? (toto.cgi?param=1//2.3)
  952.                       done=1;    // stopper
  953.                     } else {
  954.                       char tempo[HTS_URLMAXSIZE*2];
  955.                       tempo[0]='\0';
  956.                       strncat(tempo,a,(int) p - (int) a);
  957.                       strcat (tempo,p+1);
  958.                       strcpy(a,tempo);    // recopier
  959.                     }
  960.                   }
  961.                 }
  962.               } else
  963.                 lien[0]='\0';    // erreur
  964.               
  965.               // ------------------------------------------------------
  966.               // Lien repΘrΘ et extrait
  967.               if (strnotempty(lien)>0) {           // construction du lien
  968.                 char adr[HTS_URLMAXSIZE*2],fil[HTS_URLMAXSIZE*2];          // ATTENTION adr cache le "vrai" adr
  969.                 int forbidden_url=-1;              // lien non interdit (mais non autorisΘ..)
  970.                 int just_test_it=0;                // mode de test des liens
  971.                 int set_prio_to_0=0;               // pour capture de page isolΘe
  972.                 int import_done=0;                 // lien importΘ (ne pas scanner ensuite *α priori*)
  973.                 //
  974.                 adr[0]='\0'; fil[0]='\0';
  975.                 //
  976.                 // 0: autorisΘ
  977.                 // 1: interdit (patcher tout de mΩme adresse)
  978.                 
  979.                 if ((opt.debug>1) && (opt.log!=NULL)) {
  980.                   fspc(opt.log,"debug"); fprintf(opt.log,"link detected in html: %s"LF,lien); test_flush;
  981.                 }
  982.  
  983.                 // purger CR,LF rΘsiduels (IMG SRC="foo.<\n>gif")
  984.                 {
  985.                   char* a;
  986.                   while ((a=strchr(lien,'\n'))) {
  987.                     char tempo[HTS_URLMAXSIZE*2];
  988.                     tempo[0]='\0';
  989.                     strncat(tempo,lien,(int) a - (int) lien);
  990.                     strcat(tempo,a+1);
  991.                     strcpy(lien,tempo);
  992.                   }
  993.                   while ((a=strchr(lien,'\r'))) {
  994.                     char tempo[HTS_URLMAXSIZE*2];
  995.                     tempo[0]='\0';
  996.                     strncat(tempo,lien,(int) a - (int) lien);
  997.                     strcat(tempo,a+1);
  998.                     strcpy(lien,tempo);
  999.                   }
  1000.                 }
  1001.                 
  1002.                 /* Unescape/escape %20 and other   */
  1003.                 {
  1004.                   char query[HTS_URLMAXSIZE*2];
  1005.                   char* a=strchr(lien,'?');
  1006.                   if (a) {
  1007.                     strcpy(query,a);
  1008.                     *a='\0';
  1009.                   } else
  1010.                     query[0]='\0';
  1011.                   // conversion & -> & et autres joyeusetΘs
  1012.                   unescape_amp(lien);
  1013.                   // dΘcoder l'inutile (%2E par exemple) et coder espaces
  1014.                   strcpy(lien,unescape_http(lien));
  1015.                   escape_spc_url(lien);
  1016.                   strcat(lien,query);     /* restore */
  1017.                 }
  1018.                 
  1019.                 // convertir les Θventuels \ en des / pour Θviter des problΦmes de reconnaissance!
  1020.                 {
  1021.                   char* a=jump_identification(lien);
  1022.                   while( (a=strchr(a,'\\')) ) *a='/';
  1023.                 }
  1024.                 
  1025.                 // supprimer le(s) ./
  1026.                 while ((lien[0]=='.') && (lien[1]=='/')) {
  1027.                   char tempo[HTS_URLMAXSIZE*2];
  1028.                   strcpy(tempo,lien+2);
  1029.                   strcpy(lien,tempo);
  1030.                 }
  1031.                 if (strnotempty(lien)==0)  // sauf si plus de nom de fichier
  1032.                   strcpy(lien,"./");
  1033.                 
  1034.                 // vΘrifie les /~machin -> /~machin/
  1035.                 // supposition dangereuse?
  1036.                 if (lien[strlen(lien)-1]!='/') {
  1037.                   char *a=lien+strlen(lien)-1;
  1038.                   // Θviter aussi index~1.html
  1039.                   while (((int) a>(int) lien) && (*a!='~') && (*a!='/') && (*a!='.')) a--;
  1040.                   if (*a=='~') {
  1041.                     strcat(lien,"/");    // ajouter slash
  1042.                   }
  1043.                 }
  1044.                 
  1045.                 
  1046.                 // Θliminer les Θventuels :80 (port par dΘfaut!)
  1047.                 {
  1048.                   char* a;
  1049.                   a=strstr(lien,"://");
  1050.                   if (a)
  1051.                     a+=3;
  1052.                   else
  1053.                     a=lien;
  1054.                   while((*a) && (*a!='/') && (*a!=':')) a++;
  1055.                   if (*a==':') {  // port
  1056.                     int port=0;
  1057.                     char* b=a+1;
  1058.                     while(isdigit((unsigned char)*b)) { port*=10; port+=(int) (*b-'0'); b++; }
  1059.                     if (port==80) {  // port 80, default
  1060.                       char tempo[HTS_URLMAXSIZE*2];
  1061.                       tempo[0]='\0';
  1062.                       strncat(tempo,lien,(int) a-(int) lien);
  1063.                       strcat(tempo,a+3);  // sauter :80
  1064.                       strcpy(lien,tempo);
  1065.                     }
  1066.                   }
  1067.                 }
  1068.                 
  1069.                 // filtrer les parazites (mailto & cie)
  1070.                 if (strfield(lien,"mailto:")) {  // ne pas traiter
  1071.                   error=1;
  1072.                 } else if (strfield(lien,"news:")) {  // ne pas traiter
  1073.                   error=1;
  1074.                 }
  1075.                 
  1076.                 // vΘrifier que l'on ne doit pas ajouter de .class
  1077.                 if (!error) {
  1078.                   if (add_class) {
  1079.                     char *a = lien+strlen(lien)-1;
  1080.                     while(((int) a > (int) lien) && (*a!='/') && (*a!='.')) a--;
  1081.                     if (*a != '.')
  1082.                       strcat(lien,".class");    // ajouter .class
  1083.                   }
  1084.                 }
  1085.                 
  1086.                 // si c'est un chemin, alors vΘrifier (toto/toto.html -> http://www/toto/)
  1087.                 if (!error) {
  1088.                   if ((opt.debug>1) && (opt.log!=NULL)) {
  1089.                     fspc(opt.log,"debug"); fprintf(opt.log,"position link check %s"LF,lien); test_flush;
  1090.                   }
  1091.                   
  1092.                   if ((p_type==2) || (p_type==-2)) {   // code ou codebase                        
  1093.                     // VΘrifier les codebase=applet (au lieu de applet/)
  1094.                     if (p_type==-2) {    // codebase
  1095.                       if (strnotempty(lien)) {
  1096.                         if (fil[strlen(lien)-1]!='/') {  // pas rΘpertoire
  1097.                           strcat(lien,"/");
  1098.                         }
  1099.                       }
  1100.                     }
  1101.                     /* only one ending / (bug on some pages) */
  1102.                     if ((int)strlen(lien)>2) {
  1103.                       while( (lien[strlen(lien)-2]=='/') && ((int)strlen(lien)>2) )    /* double // (bug) */
  1104.                         lien[strlen(lien)-1]='\0';
  1105.                     }
  1106.                     // copier nom host si besoin est
  1107.                     if (strstr(lien,"://")==NULL) {  // pas de http://
  1108.                       char adr2[HTS_URLMAXSIZE*2],fil2[HTS_URLMAXSIZE*2];  // ** euh ident_url_relatif??
  1109.                       if (ident_url_relatif(lien,urladr,urlfil,adr2,fil2)<0) {                        
  1110.                         error=1;
  1111.                       } else {
  1112.                         strcpy(lien,"http://");
  1113.                         strcat(lien,adr2);
  1114.                         if (*fil2!='/')
  1115.                           strcat(lien,"/");
  1116.                         strcat(lien,fil2);
  1117.                         {
  1118.                           char* a;
  1119.                           a=lien+strlen(lien)-1;
  1120.                           while((*a) && (*a!='/') && ((int) a> (int) lien)) a--;
  1121.                           if (*a=='/') {
  1122.                             *(a+1)='\0';
  1123.                           }
  1124.                         }
  1125.                         //char tempo[HTS_URLMAXSIZE*2];
  1126.                         //strcpy(tempo,"http://");
  1127.                         //strcat(tempo,urladr);    // host
  1128.                         //if (*lien!='/')
  1129.                         //  strcat(tempo,"/");
  1130.                         //strcat(tempo,lien);
  1131.                         //strcpy(lien,tempo);
  1132.                       }
  1133.                     }
  1134.                     
  1135.                     if (!error) {  // pas d'erreur?
  1136.                       if (p_type==2) {   // code ET PAS codebase      
  1137.                         char* a=lien+strlen(lien)-1;
  1138.                         while( ((int) a > (int) lien) && (*a) && (*a!='/')) a--;
  1139.                         if (*a=='/')     // ok on a repΘrΘ le dernier /
  1140.                           *(a+1)='\0';   // couper
  1141.                         else {
  1142.                           *lien='\0';    // Θliminer
  1143.                           error=1;   // erreur, ne pas poursuivre
  1144.                         }      
  1145.                       }
  1146.                       
  1147.                       // stocker base ou codebase?
  1148.                       switch(p_type) {
  1149.                       case 2: { 
  1150.                         //if (*lien!='/') strcat(base,"/");
  1151.                         strcpy(base,lien);
  1152.                               }
  1153.                         break;      // base
  1154.                       case -2: {
  1155.                         //if (*lien!='/') strcat(codebase,"/");
  1156.                         strcpy(codebase,lien); 
  1157.                                }
  1158.                         break;  // base
  1159.                       }
  1160.                       
  1161.                       if ((opt.debug>1) && (opt.log!=NULL)) {
  1162.                         fspc(opt.log,"debug"); fprintf(opt.log,"code/codebase link %s base %s"LF,lien,base); test_flush;
  1163.                       }
  1164.                       //printf("base code: %s - %s\n",lien,base);
  1165.                     }
  1166.                     
  1167.                   } else {
  1168.                     char* _base;
  1169.                     if (p_type==-1)   // code (applet)
  1170.                       _base=codebase;
  1171.                     else
  1172.                       _base=base;
  1173.                     
  1174.                     // ajouter chemin de base href..
  1175.                     if (strnotempty(_base)) {       // considΘrer base
  1176.                       if (!strstr(lien,"://")) {    // non absolue
  1177.                         if (*lien!='/') {           // non absolu sur le site (/)
  1178.                           if ( ((int) strlen(_base)+(int) strlen(lien))<HTS_URLMAXSIZE) {
  1179.                             char tempo[HTS_URLMAXSIZE*2];
  1180.                             // base est absolue
  1181.                             strcpy(tempo,_base);
  1182.                             strcat(tempo,lien);
  1183.                             strcpy(lien,tempo);        // patcher en considΘrant base
  1184.                             // ** vΘrifier que ../ fonctionne (ne doit pas arriver mais bon..)
  1185.                             
  1186.                             if ((opt.debug>1) && (opt.log!=NULL)) {
  1187.                               fspc(opt.log,"debug"); fprintf(opt.log,"link modified with code/codebase %s"LF,lien); test_flush;
  1188.                             }
  1189.                           } else {
  1190.                             error=1;    // erreur
  1191.                             if (opt.errlog) {
  1192.                               fspc(opt.errlog,"error"); fprintf(opt.errlog,"Link %s too long with base href"LF,lien);
  1193.                               test_flush;
  1194.                             }
  1195.                           }
  1196.                         }
  1197.                       }
  1198.                     }
  1199.                   }
  1200.                   }
  1201.                   
  1202.                   
  1203.                   // transformer lien quelconque (http, relatif, etc) en une adresse
  1204.                   // et un chemin+fichier (adr,fil)
  1205.                   if (!error) {
  1206.                     int reponse;
  1207.                     if ((opt.debug>1) && (opt.log!=NULL)) {
  1208.                       fspc(opt.log,"debug"); fprintf(opt.log,"build relative link %s with %s%s"LF,lien,urladr,urlfil); test_flush;
  1209.                     }
  1210.                     if ((reponse=ident_url_relatif(lien,urladr,urlfil,adr,fil))<0) {                        
  1211.                       adr[0]='\0';    // erreur
  1212.                       if (reponse==-2) {
  1213.                         if (opt.errlog) {
  1214.                           fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Link %s not caught (unknown ftp:// protocol)"LF,lien);
  1215.                           test_flush;
  1216.                         }
  1217.                       }
  1218.                     }
  1219.                   } else {
  1220.                     if ((opt.debug>1) && (opt.log!=NULL)) {
  1221.                       fspc(opt.log,"debug"); fprintf(opt.log,"link %s not build, error detected before"LF,lien); test_flush;
  1222.                     }
  1223.                     adr[0]='\0';
  1224.                   }
  1225.                   
  1226. #if HTS_CHECK_STRANGEDIR
  1227.                   // !ATTENTION!
  1228.                   // Ici on teste les exotiques du genre www.truc.fr/machin (sans slash α la fin)
  1229.                   // je n'ai pas encore trouvΘ le moyen de faire la diffΘrence entre un rΘpertoire
  1230.                   // et un fichier en http A PRIORI : je fais donc un test
  1231.                   // En cas de moved xxx, on recalcule adr et fil, tout simplement
  1232.                   // DEFAUT: test effectuΘ plusieurs fois! α revoir!!!
  1233.                   if ((adr[0]!='\0') && (strcmp(adr,"file://") && (p_type!=2) && (p_type!=-2)) {
  1234.                     //## if ((adr[0]!='\0') && (adr[0]!=lOCAL_CHAR) && (p_type!=2) && (p_type!=-2)) {
  1235.                     if (fil[strlen(fil)-1]!='/') {  // pas rΘpertoire
  1236.                       if (ishtml(fil)==-2) {    // pas d'extension
  1237.                         char loc[HTS_URLMAXSIZE*2];  // Θventuelle nouvelle position
  1238.                         loc[0]='\0';
  1239.                         if ((opt.debug>1) && (opt.log!=NULL)) {
  1240.                           fspc(opt.log,"debug"); fprintf(opt.log,"link-check-directory: %s%s"LF,adr,fil);
  1241.                           test_flush;
  1242.                         }
  1243.                         
  1244.                         // tester Θventuelle nouvelle position
  1245.                         switch (http_location(adr,fil,loc).statuscode) {
  1246.                         case 200: // ok au final
  1247.                           if (strnotempty(loc)) {  // a changΘ d'adresse
  1248.                             if (opt.errlog) {
  1249.                               fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Link %s%s has moved to %s for %s%s"LF,adr,fil,loc,urladr,urlfil);
  1250.                               test_flush;
  1251.                             }
  1252.                             
  1253.                             // recalculer adr et fil!
  1254.                             if (ident_url(loc,adr,fil)==-1) {
  1255.                               adr[0]='\0';  // cancel
  1256.                               if ((opt.debug>1) && (opt.log!=NULL)) {
  1257.                                 fspc(opt.log,"debug"); fprintf(opt.log,"link-check-dir: %s%s"LF,adr,fil);
  1258.                                 test_flush;
  1259.                               }
  1260.                             }
  1261.                             
  1262.                           }
  1263.                           break;
  1264.                         case -2: case -3:  // timeout ou erreur grave
  1265.                           if (opt.errlog) {
  1266.                             fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Connection too slow for testing link %s%s (from %s%s)"LF,adr,fil,urladr,urlfil);
  1267.                             test_flush;
  1268.                           }
  1269.                           
  1270.                           break;
  1271.                         }
  1272.                         
  1273.                       }
  1274.                     } 
  1275.                   }
  1276. #endif
  1277.                   
  1278.                   // Le lien doit juste Ωtre rΘΘcrit, mais ne doit pas gΘnΘrer un lien
  1279.                   // exemple: <FORM ACTION="url_cgi">
  1280.                   if (p_nocatch) {
  1281.                     forbidden_url=1;    // interdire rΘcupΘration du lien
  1282.                     if ((opt.debug>1) && (opt.log!=NULL)) {
  1283.                       fspc(opt.log,"debug"); fprintf(opt.log,"link ignored at %s%s"LF,adr,fil);
  1284.                       test_flush;
  1285.                     }
  1286.                   }
  1287.                   
  1288.                   // Tester si un lien doit Ωtre acceptΘ ou refusΘ (wizard)
  1289.                   // forbidden_url=1 : lien refusΘ
  1290.                   // forbidden_url=0 : lien acceptΘ
  1291.                   //if ((ptr>0) && (p_type!=2) && (p_type!=-2)) {    // tester autorisations?
  1292.                   if ((p_type!=2) && (p_type!=-2)) {    // tester autorisations?
  1293.                     if (!p_nocatch) {
  1294.                       if (adr[0]!='\0') {          
  1295.                         if ((opt.debug>1) && (opt.log!=NULL)) {
  1296.                           fspc(opt.log,"debug"); fprintf(opt.log,"wizard link test at %s%s.."LF,adr,fil);
  1297.                           test_flush;
  1298.                         }
  1299.                         forbidden_url=hts_acceptlink(&opt,ptr,lien_tot,liens,
  1300.                           adr,fil,
  1301.                           filters,&filptr,filter_max,
  1302.                           &robots,
  1303.                           &set_prio_to_0,
  1304.                           &just_test_it);
  1305.                         if ((opt.debug>1) && (opt.log!=NULL)) {
  1306.                           fspc(opt.log,"debug"); fprintf(opt.log,"result for wizard link test: %d"LF,forbidden_url);
  1307.                           test_flush;
  1308.                         }
  1309.                       }
  1310.                     }
  1311.                   }
  1312.                   
  1313.                   // calculer meme_adresse
  1314.                   meme_adresse=strfield2(adr,urladr);
  1315.                   
  1316.                   
  1317.                   
  1318.                   // DΘbut partie sauvegarde
  1319.                   
  1320.                   // ici on forme le nom du fichier α sauver, et on patche l'URL
  1321.                   if (adr[0]!='\0') {
  1322.                     // savename: simplifier les ../ et autres joyeusetΘs
  1323.                     char save[HTS_URLMAXSIZE*2];
  1324.                     int r_sv=0;
  1325.                     // En cas de moved, adresse premiΦre
  1326.                     char former_adr[HTS_URLMAXSIZE*2];
  1327.                     char former_fil[HTS_URLMAXSIZE*2];
  1328.                     //
  1329.                     save[0]='\0'; former_adr[0]='\0'; former_fil[0]='\0';
  1330.                     //
  1331.                     
  1332.                     // nom du chemin α sauver si on doit le calculer
  1333.                     // note: url_savename peut dΘcider de tester le lien si il le trouve
  1334.                     // suspect, et modifier alors adr et fil
  1335.                     // dans ce cas on aura une rΘfΘrence directe au lieu des traditionnels
  1336.                     // moved en cascade (impossible α reproduire α priori en local, lorsque des fichiers
  1337.                     // gif sont impliquΘs par exemple)
  1338.                     if ((p_type!=2) && (p_type!=-2)) {  // pas base href ou codebase
  1339.                       if (forbidden_url!=1) {
  1340.                         char last_adr[HTS_URLMAXSIZE*2];
  1341.                         last_adr[0]='\0';
  1342.                         //char last_fil[HTS_URLMAXSIZE*2]="";
  1343.                         strcpy(last_adr,adr);    // ancienne adresse
  1344.                         //strcpy(last_fil,fil);    // ancien chemin
  1345.                         r_sv=url_savename(adr,fil,save,former_adr,former_fil,liens[ptr]->adr,liens[ptr]->fil,&opt,liens,lien_tot,back,back_max,&cache,&hash,ptr,numero_passe);
  1346.                         if (strcmp(last_adr,adr) != 0) {  // a changΘ
  1347.                           
  1348.                           // 2e test si moved
  1349.                           
  1350.                           // Tester si un lien doit Ωtre acceptΘ ou refusΘ (wizard)
  1351.                           // forbidden_url=1 : lien refusΘ
  1352.                           // forbidden_url=0 : lien acceptΘ
  1353.                           if ((ptr>0) && (p_type!=2) && (p_type!=-2)) {    // tester autorisations?
  1354.                             if (!p_nocatch) {
  1355.                               if (adr[0]!='\0') {          
  1356.                                 if ((opt.debug>1) && (opt.log!=NULL)) {
  1357.                                   fspc(opt.log,"debug"); fprintf(opt.log,"wizard moved link retest at %s%s.."LF,adr,fil);
  1358.                                   test_flush;
  1359.                                 }
  1360.                                 forbidden_url=hts_acceptlink(&opt,ptr,lien_tot,liens,
  1361.                                   adr,fil,
  1362.                                   filters,&filptr,filter_max,
  1363.                                   &robots,
  1364.                                   &set_prio_to_0,
  1365.                                   &just_test_it);
  1366.                                 if ((opt.debug>1) && (opt.log!=NULL)) {
  1367.                                   fspc(opt.log,"debug"); fprintf(opt.log,"result for wizard moved link retest: %d"LF,forbidden_url);
  1368.                                   test_flush;
  1369.                                 }
  1370.                               }
  1371.                             }
  1372.                           }
  1373.                           
  1374.                           //import_done=1;    // c'est un import!
  1375.                           meme_adresse=0;   // on a changΘ
  1376.                         }
  1377.                       } else {
  1378.                         strcpy(save,"");  // dummy
  1379.                       }
  1380.                     }
  1381.                     if (r_sv!=-1) {  // pas d'erreur, on continue
  1382.                       /* log */
  1383.                       if ((opt.debug>1) && (opt.log!=NULL)) {
  1384.                         fspc(opt.log,"debug");
  1385.                         if (forbidden_url!=1) {    // le lien va Ωtre chargΘ
  1386.                           if ((p_type==2) || (p_type==-2)) {  // base href ou codebase, pas un lien
  1387.                             fprintf(opt.log,"Code/Codebase: %s%s"LF,adr,fil);
  1388.                           } else if ((opt.getmode & 4)==0) {
  1389.                             fprintf(opt.log,"Record: %s%s -> %s"LF,adr,fil,save);
  1390.                           } else {
  1391.                             if (!ishtml(fil))
  1392.                               fprintf(opt.log,"Record after: %s%s -> %s"LF,adr,fil,save);
  1393.                             else
  1394.                               fprintf(opt.log,"Record: %s%s -> %s"LF,adr,fil,save);
  1395.                           } 
  1396.                         } else
  1397.                           fprintf(opt.log,"External: %s%s"LF,adr,fil);
  1398.                         test_flush;
  1399.                       }
  1400.                       /* FIN log */
  1401.                       
  1402.                       // Θcrire lien
  1403.                       if ((p_type==2) || (p_type==-2)) {  // base href ou codebase, sauter
  1404.                         lastsaved=eadr-1+1;  // sauter "
  1405.                       } else if (forbidden_url==1) {    // le lien ne sera pas chargΘ, rΘfΘrence externe!
  1406.                         if ((opt.getmode & 1) && (ptr>0)) {
  1407.                           if (p_type!=-1) {     // pas que le nom de fichier (pas classe java)
  1408.                             if (!opt.external) {
  1409.                               if (!strstr(adr,"://")) {
  1410.                                 HT_ADD("http://");
  1411.                               }
  1412.                               HT_ADD(adr);
  1413.                               if (*fil!='/')
  1414.                                 HT_ADD("/");
  1415.                               HT_ADD(fil);
  1416.                               //
  1417.                             } else {    // fichier/page externe, mais on veut gΘnΘrer une erreur
  1418.                               //
  1419.                               int patch_it=0;
  1420.                               int add_url=0;
  1421.                               char* cat_name=NULL;
  1422.                               char* cat_data=NULL;
  1423.                               int cat_data_len=0;
  1424.                               
  1425.                               // ajouter lien external
  1426.                               switch ((fil[strlen(fil)-1]=='/')?1:(ishtml(fil))) {
  1427.                               case 1: case -2:       // html ou rΘpertoire
  1428.                                 if (opt.getmode & 1) {  // sauver html
  1429.                                   patch_it=1;   // redirect
  1430.                                   add_url=1;    // avec link?
  1431.                                   cat_name="external.html";
  1432.                                   cat_data=HTS_DATA_UNKNOWN_HTML;
  1433.                                   cat_data_len=HTS_DATA_UNKNOWN_HTML_LEN;
  1434.                                 }
  1435.                                 break;
  1436.                               default:    // inconnu
  1437.                                 if ( (strfield2(fil+strlen(fil)-4,".gif")) 
  1438.                                   || (strfield2(fil+strlen(fil)-4,".jpg")) 
  1439.                                   || (strfield2(fil+strlen(fil)-4,".xbm")) 
  1440.                                   || (ishtml(fil)!=0) ) {
  1441.                                   patch_it=1;   // redirect
  1442.                                   add_url=1;    // avec link aussi
  1443.                                   cat_name="external.gif";
  1444.                                   cat_data=HTS_DATA_UNKNOWN_GIF;
  1445.                                   cat_data_len=HTS_DATA_UNKNOWN_GIF_LEN;
  1446.                                 }
  1447.                                 break;
  1448.                               }// html,gif
  1449.                               
  1450.                               if (patch_it) {
  1451.                                 char save[HTS_URLMAXSIZE*2];
  1452.                                 char tempo[HTS_URLMAXSIZE*2];
  1453.                                 strcpy(save,opt.path_html);
  1454.                                 strcat(save,cat_name);
  1455.                                 if (lienrelatif(tempo,save,savename)==0) {
  1456.                                   HT_ADD(tempo);    // page externe
  1457.                                   if (add_url) {
  1458.                                     HT_ADD("?link=");    // page externe
  1459.                                     HT_ADD(adr);
  1460.                                     if (*fil!='/')
  1461.                                       HT_ADD("/");
  1462.                                     HT_ADD(fil);
  1463.                                   }
  1464.                                 }
  1465.                                 
  1466.                                 // Θcrire fichier?
  1467.                                 if (!fexist(fconcat(opt.path_html,cat_name))) {
  1468.                                   FILE* fp = filecreate(fconcat(opt.path_html,cat_name));
  1469.                                   if (fp) {
  1470.                                     if (cat_data_len==0) {   // texte
  1471.                                       verif_backblue(opt.path_html);
  1472.                                       fprintf(fp,"%s%s","<!-- Created by HTTrack Website Copier/"HTTRACK_VERSION" "HTTRACK_AFF_AUTHORS" -->"LF,cat_data);
  1473.                                     } else {                    // data
  1474.                                       fwrite(cat_data,cat_data_len,1,fp);
  1475.                                     }
  1476.                                     fclose(fp);
  1477.                                     usercommand(0,NULL,fconcat(opt.path_html,cat_name));
  1478.                                   }
  1479.                                 }
  1480.                               }  else {    // Θcrire normalement le nom de fichier
  1481.                                 HT_ADD("http://");
  1482.                                 HT_ADD(adr);
  1483.                                 if (*fil!='/')
  1484.                                   HT_ADD("/");
  1485.                                 HT_ADD(fil);
  1486.                               }// patcher?
  1487.                             }  // external
  1488.                           } else {  // que le nom de fichier (classe java)
  1489.                             // en gros recopie de plus bas: copier codebase et base
  1490.                             if (p_flush) {
  1491.                               char tempo[HTS_URLMAXSIZE*2];    // <-- ajoutΘ
  1492.                               char tempo_pat[HTS_URLMAXSIZE*2];
  1493.                               tempo_pat[0]='\0';
  1494.                               strcpy(tempo,fil);  // <-- ajoutΘ
  1495.                               {
  1496.                                 char* a=tempo+strlen(tempo)-1;
  1497.                                 while( ((int) a > (int) tempo) && (*a) && (*a!='/')) a--;
  1498.                                 if (*a=='/') {
  1499.                                   char tempo2[HTS_URLMAXSIZE*2];
  1500.                                   strcpy(tempo2,a+1);
  1501.                                   strncat(tempo_pat,tempo,(int) a-(int) tempo+1);  // chemin
  1502.                                   strcpy(tempo,tempo2);                     // fichier
  1503.                                 }
  1504.                               }
  1505.                               
  1506.                               // Θrire codebase="chemin"
  1507.                               if ((opt.getmode & 1) && (ptr>0)) {
  1508.                                 char tempo4[HTS_URLMAXSIZE*2];
  1509.                                 tempo4[0]='\0';
  1510.                                 
  1511.                                 if (strnotempty(tempo_pat)) {
  1512.                                   HT_ADD("codebase=\"http://");
  1513.                                   HT_ADD(adr);
  1514.                                   if (*tempo_pat!='/') HT_ADD("/");
  1515.                                   HT_ADD(tempo_pat);
  1516.                                   HT_ADD("\" ");
  1517.                                 }
  1518.                                 
  1519.                                 strncat(tempo4,lastsaved,(int) p_flush-(int) lastsaved);
  1520.                                 HT_ADD(tempo4);    // refresh code="
  1521.                                 HT_ADD(tempo);
  1522.                               }
  1523.                             }
  1524.                           }
  1525.                         }
  1526.                         lastsaved=eadr-1;
  1527.                       } 
  1528.                       /*
  1529.                       else if (opt.urlmode==1) {    // ABSOLU, c'est le cas le moins courant
  1530.                       //  NE FONCTIONNE PAS!!  (et est inutile)
  1531.                       if ((opt.getmode & 1) && (ptr>0)) {    // ecrire les html
  1532.                       // Θcrire le lien modifiΘ, absolu
  1533.                       HT_ADD("file:");
  1534.                       if (*save=='/')
  1535.                       HT_ADD(save+1)
  1536.                       else
  1537.                       HT_ADD(save)
  1538.                       }
  1539.                       lastsaved=eadr-1;    // dernier Θcrit+1 (enfin euh apres on fait un ++ alors hein)
  1540.                       }
  1541.                       */
  1542.                       else if (opt.urlmode==2) {  // RELATIF
  1543.                         char tempo[HTS_URLMAXSIZE*2];
  1544.                         tempo[0]='\0';
  1545.                         // calculer le lien relatif
  1546.                         
  1547.                         if (lienrelatif(tempo,save,savename)==0) {
  1548.                           if ((opt.debug>1) && (opt.log!=NULL)) {
  1549.                             fspc(opt.log,"debug"); fprintf(opt.log,"relative link at %s build with %s and %s: %s"LF,adr,save,savename,tempo);
  1550.                             test_flush;
  1551.                           }
  1552.                           
  1553.                           // lien applet (code) - il faut placer un codebase avant
  1554.                           if (p_type==-1) {  // que le nom de fichier
  1555.                             
  1556.                             if (p_flush) {
  1557.                               char tempo_pat[HTS_URLMAXSIZE*2];
  1558.                               tempo_pat[0]='\0';
  1559.                               {
  1560.                                 char* a=tempo+strlen(tempo)-1;
  1561.                                 while( ((int) a > (int) tempo) && (*a) && (*a!='/')) a--;
  1562.                                 if (*a=='/') {
  1563.                                   char tempo2[HTS_URLMAXSIZE*2];
  1564.                                   strcpy(tempo2,a+1);
  1565.                                   strncat(tempo_pat,tempo,(int) a-(int) tempo+1);  // chemin
  1566.                                   strcpy(tempo,tempo2);                     // fichier
  1567.                                 }
  1568.                               }
  1569.                               
  1570.                               // Θrire codebase="chemin"
  1571.                               if ((opt.getmode & 1) && (ptr>0)) {
  1572.                                 char tempo4[HTS_URLMAXSIZE*2];
  1573.                                 tempo4[0]='\0';
  1574.                                 
  1575.                                 if (strnotempty(tempo_pat)) {
  1576.                                   HT_ADD("codebase=\"");
  1577.                                   HT_ADD(tempo_pat);
  1578.                                   HT_ADD("\" ");
  1579.                                 }
  1580.                                 
  1581.                                 strncat(tempo4,lastsaved,(int) p_flush-(int) lastsaved);
  1582.                                 HT_ADD(tempo4);    // refresh code="
  1583.                               }
  1584.                             }
  1585.                             //lastsaved=adr;    // dernier Θcrit+1
  1586.                           }                              
  1587.                           
  1588.                           if ((opt.getmode & 1) && (ptr>0)) {
  1589.                             // Θcrire le lien modifiΘ, relatif
  1590.                             HT_ADD(tempo);
  1591.                           }
  1592.                           lastsaved=eadr-1;    // dernier Θcrit+1 (enfin euh apres on fait un ++ alors hein)
  1593.                         } else {
  1594.                           if (opt.errlog) {
  1595.                             fprintf(opt.errlog,"Error building relative link %s and %s"LF,save,savename);
  1596.                             test_flush;
  1597.                           }
  1598.                         }
  1599.                       }  // sinon le lien sera Θcrit normalement
  1600.                       
  1601.                       
  1602. #if 0
  1603.                       if (fexist(save)) {    // le fichier existe..
  1604.                         adr[0]='\0';
  1605.                         //if ((opt.debug>0) && (opt.log!=NULL)) {
  1606.                         if (opt.errlog) {
  1607.                           fspc(opt.errlog,"warning"); fprintf(opt.errlog,"Link has already been written on disk, cancelled: %s"LF,save);
  1608.                           test_flush;
  1609.                         }
  1610.                       }
  1611. #endif                            
  1612.                       
  1613.                       if ((adr[0]!='\0') && (p_type!=2) && (p_type!=-2) && ( (forbidden_url!=1) || (just_test_it))) {  // si le fichier n'existe pas, ajouter α la liste                            
  1614.                         // n'y a-t-il pas trop de liens?
  1615.                         if (lien_tot+1 >= lien_max-4) {    // trop de liens!
  1616.                           printf("PANIC! : Too many URLs : >%d [%d]\n",lien_tot,__LINE__);
  1617.                           if (opt.errlog) {
  1618.                             fprintf(opt.errlog,LF"Too many URLs, giving up..(>%d)"LF,lien_max);
  1619.                             fprintf(opt.errlog,"To avoid that: use #L option for more links (example: -#L1000000)"LF);
  1620.                             test_flush;
  1621.                           }
  1622.                           if ((opt.getmode & 1) && (ptr>0)) { if (fp) { fclose(fp); fp=NULL; } }
  1623.                           XH_uninit    // dΘsallocation mΘmoire & buffers
  1624.                             return 0;
  1625.                           
  1626.                         } else {    // noter le lien sur la listes des liens α charger
  1627.                           int pass_fix,dejafait=0;
  1628.                           
  1629.                           // Calculer la prioritΘ de ce lien
  1630.                           if ((opt.getmode & 4)==0) {    // traiter html aprΦs
  1631.                             pass_fix=0;
  1632.                           } else {    // vΘrifier que ce n'est pas un !html
  1633.                             if (!ishtml(fil))
  1634.                               pass_fix=1;        // prioritΘ infΘrieure (traiter aprΦs)
  1635.                             else
  1636.                               pass_fix=max(0,numero_passe);    // prioritΘ normale
  1637.                           }
  1638.                           
  1639.                           // vΘrifier que le lien n'a pas dΘja ΘtΘ notΘ
  1640.                           // si c'est le cas, alors il faut s'assurer que la prioritΘ associΘe
  1641.                           // au fichier est la plus grande des deux prioritΘs
  1642.                           //
  1643.                           // On part de la fin et on essaye de se presser (Θconomise temps machine)
  1644. #if HTS_HASH
  1645.                           {
  1646.                             int i=hash_read(&hash,save,"",0);      // lecture type 0 (sav)
  1647.                             if (i>=0) {
  1648.                               liens[i]->prio=maximum(liens[i]->prio,level-1);
  1649.                               dejafait=1;
  1650.                             }
  1651.                           }
  1652. #else
  1653.                           {
  1654.                             register int l;
  1655.                             register int i;
  1656.                             l=strlen(save);  // opti
  1657.                             for(i=lien_tot-1;(i>=0) && (dejafait==0);i--) {
  1658.                               if (liens[i]->sav_len==l) {    // mΩme taille de chaεne
  1659.                                 if (strcmp(liens[i]->sav,save)==0) {    // existe dΘja
  1660.                                   liens[i]->prio=maximum(liens[i]->prio,level-1);
  1661.                                   dejafait=1;
  1662.                                 }
  1663.                               }
  1664.                             }
  1665.                           }
  1666. #endif
  1667.                           
  1668.                           // le lien n'a jamais ΘtΘ crΘΘ.
  1669.                           // cette fois ci, on le crΘe!
  1670.                           if (!dejafait) {                                
  1671.                             //
  1672.                             // >>>> CREER LE LIEN <<<<
  1673.                             //
  1674.                             // enregistrer lien α charger
  1675.                             //liens[lien_tot]->adr[0]=liens[lien_tot]->fil[0]=liens[lien_tot]->sav[0]='\0';
  1676.                             // mΩme adresse: l'objet pΦre est l'objet pΦre de l'actuel
  1677.                             
  1678.                             // DEBUT ROBOTS.TXT AJOUT
  1679.                             if (!just_test_it) {
  1680.                               if (strfield(adr,"ftp://")==0) {    // non ftp
  1681.                                 if (opt.robots) {    // rΘcupΘrer robots
  1682.                                   if (ishtml(fil)!=0) {                       // pas la peine pour des fichiers isolΘs
  1683.                                     if (checkrobots(&robots,adr,"") != -1) {    // robots.txt ?
  1684.                                       checkrobots_set(&robots,adr,"");          // ajouter entrΘe vide
  1685.                                       if (checkrobots(&robots,adr,"") == -1) {    // robots.txt ?
  1686.                                         // enregistrer robots.txt (MACRO)
  1687.                                         liens_record(adr,"/robots.txt","","","");
  1688.                                         if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  1689.                                           printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1690.                                           if (opt.errlog) { 
  1691.                                             fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1692.                                             test_flush;
  1693.                                           }
  1694.                                           if ((opt.getmode & 1) && (ptr>0)) { if (fp) { fclose(fp); fp=NULL; } }
  1695.                                           XH_uninit;    // dΘsallocation mΘmoire & buffers
  1696.                                           return 0;
  1697.                                         }  
  1698.                                         liens[lien_tot]->testmode=0;          // pas mode test
  1699.                                         liens[lien_tot]->link_import=0;       // pas mode import     
  1700.                                         liens[lien_tot]->premier=lien_tot;
  1701.                                         liens[lien_tot]->precedent=ptr;
  1702.                                         liens[lien_tot]->prio=0;
  1703.                                         liens[lien_tot]->pass2=max(0,numero_passe);
  1704.                                         liens[lien_tot]->retry=0;
  1705.                                         lien_tot++;  // UN LIEN DE PLUS
  1706. #if DEBUG_ROBOTS
  1707.                                         printf("robots.txt: added file robots.txt for %s\n",adr);
  1708. #endif
  1709.                                         if ((opt.debug>1) && (opt.log!=NULL)) {
  1710.                                           fspc(opt.log,"debug"); fprintf(opt.log,"robots.txt added at %s"LF,adr);
  1711.                                           test_flush;
  1712.                                         }
  1713.                                       } else {
  1714.                                         if (opt.errlog) {   
  1715.                                           fprintf(opt.errlog,"Unexpected robots.txt error at %d"LF,__LINE__);
  1716.                                           test_flush;
  1717.                                         }
  1718.                                       }
  1719.                                     }
  1720.                                   }
  1721.                                 }
  1722.                               }
  1723.                             }
  1724.                             // FIN ROBOTS.TXT AJOUT
  1725.                             
  1726.                             // enregistrer (MACRO)
  1727.                             liens_record(adr,fil,save,former_adr,former_fil);
  1728.                             if (liens[lien_tot]==NULL) {  // erreur, pas de place rΘservΘe
  1729.                               printf("PANIC! : Not enough memory [%d]\n",__LINE__);
  1730.                               if (opt.errlog) { 
  1731.                                 fprintf(opt.errlog,"Not enough memory, can not re-allocate %d bytes"LF,(add_tab_alloc+1)*sizeof(lien_url));
  1732.                                 test_flush;
  1733.                               }
  1734.                               if ((opt.getmode & 1) && (ptr>0)) { if (fp) { fclose(fp); fp=NULL; } }
  1735.                               XH_uninit;    // dΘsallocation mΘmoire & buffers
  1736.                               return 0;
  1737.                             }  
  1738.                             
  1739.                             // mode test?
  1740.                             if (!just_test_it)
  1741.                               liens[lien_tot]->testmode=0;          // pas mode test
  1742.                             else
  1743.                               liens[lien_tot]->testmode=1;          // mode test
  1744.                             if (!import_done)
  1745.                               liens[lien_tot]->link_import=0;       // pas mode import
  1746.                             else
  1747.                               liens[lien_tot]->link_import=1;       // mode import
  1748.                             // Θcrire autres paramΦtres de la structure-lien
  1749.                             if ((meme_adresse) && (!import_done) && (liens[ptr]->premier != 0))
  1750.                               liens[lien_tot]->premier=liens[ptr]->premier;
  1751.                             else    // sinon l'objet pΦre est le prΘcΘdent lui mΩme
  1752.                               liens[lien_tot]->premier=lien_tot;
  1753.                             // liens[lien_tot]->premier=ptr;
  1754.                             
  1755.                             liens[lien_tot]->precedent=ptr;
  1756.                             // noter la prioritΘ
  1757.                             if (!set_prio_to_0)
  1758.                               liens[lien_tot]->prio=level-1;
  1759.                             else
  1760.                               liens[lien_tot]->prio=0;         // PRIORITE NULLE (catch page)
  1761.                             // noter pass
  1762.                             liens[lien_tot]->pass2=pass_fix;
  1763.                             liens[lien_tot]->retry=opt.retry;
  1764.                             
  1765.                             //strcpy(liens[lien_tot]->adr,adr);
  1766.                             //strcpy(liens[lien_tot]->fil,fil);
  1767.                             //strcpy(liens[lien_tot]->sav,save); 
  1768.                             if ((opt.debug>1) && (opt.log!=NULL)) {
  1769.                               if (!just_test_it) {
  1770.                                 fspc(opt.log,"debug"); fprintf(opt.log,"OK, NOTE: %s%s -> %s"LF,liens[lien_tot]->adr,liens[lien_tot]->fil,liens[lien_tot]->sav);
  1771.                               } else {
  1772.                                 fspc(opt.log,"debug"); fprintf(opt.log,"OK, TEST: %s%s"LF,liens[lien_tot]->adr,liens[lien_tot]->fil);
  1773.                               }
  1774.                               test_flush;
  1775.                             }
  1776.                             
  1777.                             lien_tot++;  // UN LIEN DE PLUS
  1778.                           } else { // if !dejafait
  1779.                             if ((opt.debug>1) && (opt.log!=NULL)) {
  1780.                               fspc(opt.log,"debug"); fprintf(opt.log,"link has already been recorded, cancelled: %s"LF,save);
  1781.                               test_flush;
  1782.                             }
  1783.                             
  1784.                           }
  1785.                           
  1786.                           
  1787.                         }   // si pas trop de liens
  1788.                       }   // si adr[0]!='\0'
  1789.                       
  1790.                       
  1791.                     }  // if adr[0]!='\0' 
  1792.                     
  1793.                   }  // if adr[0]!='\0'
  1794.                   
  1795.                 }    // if strlen(lien)>0
  1796.                 
  1797.               }   // if ok==0      
  1798.               
  1799.               adr=eadr-1;  // ** sauter
  1800.               
  1801.             }  // if (p) 
  1802.             
  1803.           }  // si '<' ou '>'
  1804.           
  1805.           // plus loin
  1806.           adr++;  
  1807.           
  1808.           // ----------
  1809.           // Θcrire peu α peu
  1810.           if ((opt.getmode & 1) && (ptr>0)) HT_ADD_ADR;
  1811.           lastsaved=adr;    // dernier Θcrit+1
  1812.           // ----------
  1813.           
  1814.           // pour les stats du shell si parsing trop long
  1815. #if HTS_ANALYSTE==2
  1816.           _hts_in_html_done=(100 * ((int) adr - (int) r.adr) ) / (int)(r.size);
  1817.           if (_hts_in_html_poll) {
  1818.             LLint nb;
  1819.             _hts_in_html_poll=0;
  1820.             // temps α attendre, et remplir autant que l'on peut le cache (backing)
  1821.             back_wait(back,back_max,&opt,&cache,stat_timestart);        
  1822.             back_fillmax(back,back_max,&opt,&cache,liens,ptr,numero_passe,lien_tot);
  1823.             
  1824.             nb=back_transfered(stat_bytes,back,back_max);
  1825.             //if (!hts_htmlcheck_loop(back,back_max,-1,ptr,lien_tot,nb,new_stat_bytes,(int) (time_local()-stat_timestart),back_nsoc(back,back_max) )) {
  1826.             if (!hts_htmlcheck_loop(back,back_max,0,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") )) {
  1827.               if (opt.errlog) {
  1828.                 fspc(opt.errlog,"info"); fprintf(opt.errlog,"Exit requested by shell or user"LF);
  1829.                 test_flush;
  1830.               } 
  1831.               exit_xh=1;  // exit requested
  1832.               XH_uninit;
  1833.               return 0;
  1834.               //adr = r.adr + r.size;  // exit
  1835.             } else if (_hts_cancel==1) {
  1836.               adr = r.adr + r.size;  // exit
  1837.               _hts_cancel=0;
  1838.             }
  1839.           }
  1840. #endif
  1841.         } while(( ((int) adr) - ((int) r.adr) ) < r.size);
  1842. #if HTS_ANALYSTE==2
  1843.         _hts_in_html_parsing=0;  // flag
  1844.         _hts_cancel=0;           // pas de cancel
  1845. #endif
  1846.         if ((opt.getmode & 1) && (ptr>0)) {
  1847.           HT_ADD_END;    // achever
  1848.         }
  1849.         //
  1850.         //
  1851.         //
  1852.       }  // if !error
  1853.       
  1854.       
  1855.       if (opt.getmode & 1) { if (fp) { fclose(fp); fp=NULL; } }
  1856.       // sauver fichier
  1857.       //structcheck(savename);
  1858.       //filesave(r.adr,r.size,savename);
  1859.       
  1860. #if HTS_ANALYSTE
  1861.     }  // analyse OK
  1862. #endif
  1863.         
  1864.