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

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche, Yann Philippot and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. This project has been developed by Xavier Roche and Yann Philippot,
  29. from the company Serianet at Caen, France (http://www.serianet.com)
  30. and other contributors (see the greetings file)
  31.  
  32. Please visit our Website: http://www.httrack.com
  33. */
  34.  
  35.  
  36. /* ------------------------------------------------------------ */
  37. /* File: httrack.c subroutines:                                 */
  38. /*       savename routine (compute output filename)             */
  39. /* Author: Xavier Roche                                         */
  40. /* ------------------------------------------------------------ */
  41.  
  42. #include "htsname.h"
  43.  
  44. /* specific definitions */
  45. #include "htsbase.h"
  46. #include "htstools.h"
  47. #include "htsmd5.h"
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <ctype.h>
  51. /* END specific definitions */
  52.  
  53. #undef test_flush
  54. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  55.  
  56. #define ADD_STANDARD_PATH \
  57.     {  /* ajout nom */\
  58.       char buff[HTS_URLMAXSIZE*2];\
  59.       buff[0]='\0';\
  60.       strncat(buff,start_pos,(int) nom_pos - (int) start_pos);\
  61.       url_savename_addstr(save,buff);\
  62.     }
  63.  
  64. #define ADD_STANDARD_NAME(shortname) \
  65.     {  /* ajout nom */\
  66.       char buff[HTS_URLMAXSIZE*2];\
  67.       standard_name(buff,dot_pos,nom_pos,fil_complete,(shortname));\
  68.       url_savename_addstr(save,buff);\
  69.     }
  70.  
  71.  
  72. /* Avoid stupid DOS system folders/file such as 'nul' */
  73. /* Based on linux/fs/umsdos/mangle.c */
  74. static const char *hts_tbdev[] =
  75. {
  76.     "/prn", "/con", "/aux", "/nul",
  77.     "/lpt1", "/lpt2", "/lpt3", "/lpt4",
  78.     "/com1", "/com2", "/com3", "/com4",
  79.     "/clock$",
  80.     "/emmxxxx0", "/xmsxxxx0", "/setverxx",
  81.     ""
  82. };
  83.  
  84.  
  85.  
  86. // forme le nom du fichier α sauver (save) α partir de fil et adr
  87. // systΦme intelligent, qui renomme en cas de besoin (exemple: deux INDEX.HTML et index.html)
  88. int url_savename(char* adr_complete,char* fil_complete,char* save,char* former_adr,char* former_fil,char* referer_adr,char* referer_fil,httrackp* opt,lien_url** liens,int lien_tot,lien_back* back,int back_max,cache_back* cache,hash_struct* hash,int ptr,int numero_passe) {
  89.   char newfil[HTS_URLMAXSIZE*2];   /* ="" */
  90.   char* fil;
  91.   char* adr;
  92.   char* print_adr;
  93.   char *start_pos=NULL,*nom_pos=NULL,*dot_pos=NULL;  // Position nom et point
  94.   // pour changement d'extension ou de nom (content-disposition)
  95.   int ext_chg=0;
  96.   char ext[256];
  97.   //CLEAR
  98.   newfil[0]=ext[0]='\0';
  99.  
  100.   // effacer save
  101.   save[0]='\0';
  102.   // fil
  103.   fil = fil_complete;
  104.   // et adr (sauter user/pass)
  105.   // on prend le parti de mettre les fichiers avec login/pass au mΩme endroit que si ils
  106.   // Θtaient capturΘs sans ces paramΦtres
  107.   // c'est pour cette raison qu'on ignore totalement adr_complete (mΩme pour la recherche en table de hachage)
  108.   adr=jump_identification(adr_complete);
  109.  
  110.   // α afficher sans ftp://
  111.   print_adr=jump_protocol(adr);
  112.  
  113.   // court-circuit pour lien primaire
  114.   if (strnotempty(adr)==0) {
  115.     if (strcmp(fil,"primary")==0) {
  116.       strcat(save,"primary.html");
  117.       return 0;
  118.     }
  119.   }
  120.  
  121.  
  122.   // vΘrifier que le nom n'a pas dΘja ΘtΘ calculΘ (si oui le renvoyer tel que)
  123.   // vΘrifier que le nom n'est pas dΘja pris...
  124.   // NOTE: si on cherche /toto/ et que /toto est trouvΘ on le prend (et rΘciproquqment) ** // **
  125.   if (liens!=NULL) { 
  126.     register int i;
  127.  
  128. #if HTS_HASH
  129.     i=hash_read(hash,adr,fil_complete,1);      // recherche table 1 (adr+fil)
  130.     if (i>=0) {    // ok, trouvΘ
  131.       strcpy(save,liens[i]->sav);
  132.       return 0;
  133.     }
  134.     i=hash_read(hash,adr,fil_complete,2);      // recherche table 2 (former_adr+former_fil)
  135.     if (i>=0) {    // ok, trouvΘ
  136.       // copier location moved!
  137.       strcpy(adr_complete,liens[i]->adr);
  138.       strcpy(fil_complete,liens[i]->fil);
  139.       // et save
  140.       strcpy(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  141.       return 0;
  142.     }
  143. #else
  144.     for(i=lien_tot-1;i>=0;i--) {        
  145. #if HTS_CASSE
  146.       if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  147. #else
  148.       if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  149. #endif
  150.       {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  151.         strcpy(save,liens[i]->sav);
  152.         return 0;
  153.       }
  154.       if (liens[i]->former_adr) {     // tester ancienne loc?
  155. #if HTS_CASSE
  156.         if ((strcmp(liens[i]->former_adr,adr)==0) && (strcmp(liens[i]->former_fil,fil_complete)==0))
  157. #else
  158.         if ((strfield2(liens[i]->former_adr,adr)) && (strfield2(liens[i]->former_fil,fil_complete)))
  159. #endif
  160.         {
  161.           // copier location moved!
  162.           strcpy(adr_complete,liens[i]->adr);
  163.           strcpy(fil_complete,liens[i]->fil);
  164.           // et save
  165.           strcpy(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  166.           return 0;
  167.         }
  168.       }
  169.     }
  170. #endif
  171.  
  172.     // chercher sans / ou avec / dans former
  173.     {
  174.       char fil_complete_patche[HTS_URLMAXSIZE*2];
  175.       strcpy(fil_complete_patche,fil_complete);
  176.       // Version avec ou sans /
  177.       if (fil_complete_patche[strlen(fil_complete_patche)-1]=='/')
  178.         fil_complete_patche[strlen(fil_complete_patche)-1]='\0';
  179.       else
  180.         strcat(fil_complete_patche,"/");
  181. #if HTS_HASH
  182.       i=hash_read(hash,adr,fil_complete_patche,2);      // recherche table 2 (former_adr+former_fil)
  183.       if (i>=0) {
  184.         // Θcraser fil et adr (pas former_fil?????)
  185.         strcpy(adr_complete,liens[i]->adr);
  186.         strcpy(fil_complete,liens[i]->fil);
  187.         // Θcrire save
  188.         strcpy(save,liens[i]->sav);
  189.         return 0;
  190.       }
  191. #else
  192.       // mΩme boucle en gros
  193.       for(i=lien_tot-1;i>=0;i--) {        
  194.         if (liens[i]->former_adr) {    // former-adr?
  195. #if HTS_CASSE
  196.           if ((strcmp(liens[i]->former_adr,adr)==0) && (strcmp(liens[i]->former_fil,fil_complete_patche)==0))
  197. #else
  198.           if ((strfield2(liens[i]->former_adr,adr)) && (strfield2(liens[i]->former_fil,fil_complete_patche)))
  199. #endif
  200.           {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  201.             // Θcraser fil et adr (pas former_fil?????)
  202.             strcpy(adr_complete,liens[i]->adr);
  203.             strcpy(fil_complete,liens[i]->fil);
  204.             // Θcrire save
  205.             strcpy(save,liens[i]->sav);
  206.             return 0;
  207.           }
  208.         }
  209.       }
  210. #endif
  211.     }
  212.   }
  213.  
  214.   // vΘrifier la non prΘsence de paramΦtres dans le nom de fichier
  215.   // si il y en a, les supprimer (ex: truc.cgi?subj=aspirateur)
  216.   // nΘanmoins, gardΘ pour vΘrifier la non duplication (voir aprΦs)
  217.   {
  218.     char* a;
  219.     a=strchr(fil,'?');
  220.     if (a!=NULL) {
  221.       strncat(newfil,fil,(int) a-(int) fil);
  222.     } else {
  223.       strcpy(newfil,fil);
  224.     }
  225.     fil=newfil;
  226.   }
  227.   // dΘcoder %
  228.   strcpy(fil,unescape_http(fil));
  229.   /*
  230.   {
  231.     char tempo[HTS_URLMAXSIZE*2];
  232.     int i,j=0;
  233.     for (i=0;i<(int) strlen(fil);i++) {
  234.       if (fil[i]=='%') {
  235.         i++;
  236.         tempo[j++]=(char) ehex(fil+i);
  237.         i++;    // sauter 2 caractΦres finalement
  238.       } else
  239.         tempo[j++]=fil[i];
  240.     }
  241.     tempo[j++]='\0';
  242.     strcpy(fil,tempo);
  243.   }
  244.   */
  245.  
  246.  
  247.   /* replace shtml to html.. */
  248.   if (ishtml(fil)==1) {       /* .html,.shtml,.. */
  249.     if ( 
  250.       (strcmp(get_ext(fil),"html") != 0)
  251.       && (strcmp(get_ext(fil),"htm") != 0)
  252.       ) {
  253.         strcpy(ext,"html");
  254.         ext_chg=1;
  255.     }
  256.   }
  257.  
  258.  
  259.   // si option check_type activΘe
  260.   if ((opt->check_type) && (!ext_chg)) {
  261.     if ( (strncmp(adr_complete,"file://",7)) && (strncmp(adr_complete,"ftp://",6)) ) {
  262.       // tester type avec requΦte HEAD si on ne connait pas le type du fichier
  263.       if (!(   (opt->check_type==1) && (fil[strlen(fil)-1]=='/')   ))    // slash doit Ωtre html?
  264.       if (ishtml(fil)<0) { // on ne sait pas si c'est un html ou un fichier..
  265.         // lire dans le cache
  266.         htsblk r = cache_read(opt,cache,adr,fil,NULL);              // test uniquement
  267.         if (r.statuscode != -1) {  // pas d'erreur de lecture cache
  268.           char s[16]; s[0]='\0';
  269.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  270.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type (from cache) %s%s"LF,adr_complete,fil_complete);
  271.             test_flush;
  272.           }
  273.           if (strnotempty(r.cdispo)) {        /* filename given */
  274.             ext_chg=2;      /* change filename */
  275.             strcpy(ext,r.cdispo);
  276.           }
  277.           else if (!may_unknown(r.contenttype)) {  // on peut patcher α priori?
  278.             give_mimext(s,r.contenttype);  // obtenir extension
  279.             if (strnotempty(s)>0) {        // on a reconnu l'extension
  280.               ext_chg=1;
  281.               strcpy(ext,s);
  282.             }
  283.           }
  284.           //
  285.         } else {          // test imposible dans le cache, faire une requΩte
  286.           //
  287. #if HTS_ANALYSTE==2
  288.           int hihp=_hts_in_html_parsing;
  289. #endif
  290.           int has_been_moved=0;
  291.           char curr_adr[HTS_URLMAXSIZE*2],curr_fil[HTS_URLMAXSIZE*2];
  292.           curr_adr[0]=curr_fil[0]='\0';
  293. #if HTS_ANALYSTE==2
  294.           _hts_in_html_parsing=2;  // test
  295. #endif
  296.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  297.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type %s%s"LF,adr_complete,fil_complete);
  298.             test_flush;
  299.           }
  300.           strcpy(curr_adr,adr_complete);
  301.           strcpy(curr_fil,fil_complete);
  302.           // ajouter dans le backing le fichier en mode test
  303.           // savename: rien car en mode test
  304.           if (back_add(back,back_max,opt,cache,curr_adr,curr_fil,BACK_ADD_TEST,referer_adr,referer_fil,1,NULL)!=-1) {
  305.             int b;
  306.             b=back_index(back,back_max,curr_adr,curr_fil,BACK_ADD_TEST);         
  307.             if (b>=0) {
  308.               int petits_tours=0;
  309.               int get_test_request=0;       // en cas de bouclage sur soi mΩme avec HEAD, tester avec GET.. parfois c'est la cause des problΦmes
  310.               do {
  311.                 // temps α attendre, et remplir autant que l'on peut le cache (backing)
  312.                 if (back[b].status>0) back_wait(back,back_max,opt,cache,0);        
  313.                 if (ptr>=0)
  314.                   back_fillmax(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  315.   
  316.                 // on est obligΘ d'appeler le shell pour le refresh..
  317. #if HTS_ANALYSTE==2
  318.                 {
  319.                   LLint nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  320.                   int nbk=backlinks_done(liens,lien_tot,ptr);
  321.                   engine_stats();
  322.                   //if (!hts_htmlcheck_loop(back,back_max,b,-1,lien_tot,-1,-1,-1,back_nsoc(back,back_max) )) {
  323.                   if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,nb,-1,-1,back_nsoc(back,back_max),-1,-1,-1,(int)HTS_STAT.rate,nbk )) {
  324.                     return -1;
  325.                   } else if (_hts_cancel) {    // cancel 2 ou 1 (cancel parsing)
  326.                     back_delete(back,b);       // cancel test
  327.                   }
  328.                 }
  329. #endif
  330.                 
  331.                 
  332.                 // traitement des 304,303..
  333.                 if (back[b].status<=0) {
  334.                   if (    (back[b].r.statuscode==301)
  335.                        || (back[b].r.statuscode==302)
  336.                        || (back[b].r.statuscode==303)
  337.                        || (back[b].r.statuscode==307)
  338.                      ) {    // agh moved.. un tit tour de plus
  339.                     if ((petits_tours<5) && (former_adr) && (former_fil)) { // on va pas tourner en rond non plus!
  340.                       if ((int) strnotempty(back[b].r.location)) {    // location existe!
  341.                         char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  342.                         mov_url[0]=mov_adr[0]=mov_fil[0]='\0';
  343.                         //
  344.                         strcpy(mov_url,back[b].r.location);    // copier URL
  345.                         if (ident_url_relatif(mov_url,curr_adr,curr_fil,mov_adr,mov_fil)>=0) {                        
  346.                           // si non bouclage sur soi mΩme, ou si test avec GET non testΘ
  347.                           if ((strcmp(mov_adr,curr_adr)) || (strcmp(mov_fil,curr_fil)) || (get_test_request==0)) {
  348.                             // bouclage?
  349.                             if ((!strcmp(mov_adr,curr_adr)) && (!strcmp(mov_fil,curr_fil)))
  350.                               get_test_request=1;     // faire requΦte avec GET
  351.  
  352.                             // recopier former_adr/fil?
  353.                             if ((former_adr) && (former_fil)) {
  354.                               if (strnotempty(former_adr)==0) {    // Pas dΘja notΘ
  355.                                 strcpy(former_adr,curr_adr);
  356.                                 strcpy(former_fil,curr_fil);
  357.                               }
  358.                             }
  359.  
  360.                             // ftp: stop!
  361.                             if (!strncmp(mov_url,"ftp://",6)) {    // ftp, ok on arrΩte
  362.                               has_been_moved = 1;
  363.                               back_delete(back,b);    // ok
  364.                               strcpy(curr_adr,mov_adr);
  365.                               strcpy(curr_fil,mov_fil);
  366.                             } else {
  367.                               char* methode;
  368.                               if (!get_test_request)
  369.                                 methode=BACK_ADD_TEST;      // tester avec HEAD
  370.                               else {
  371.                                 methode=BACK_ADD_TEST2;     // tester avec GET
  372.                                 if ( opt->errlog!=NULL ) {
  373.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Loop with HEAD request (during prefetch) at %s%s"LF,curr_adr,curr_fil);
  374.                                   test_flush;
  375.                                 }                    
  376.                               }
  377.                               // Ajouter
  378.                               if (back_add(back,back_max,opt,cache,mov_adr,mov_fil,methode,referer_adr,referer_fil,1,NULL)!=-1) {    // OK
  379.                                 if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  380.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"(during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  381.                                   test_flush;
  382.                                 }                    
  383.                                 
  384.                                 // libΘrer emplacement backing actuel et attendre le prochain
  385.                                 back_delete(back,b);
  386.                                 strcpy(curr_adr,mov_adr);
  387.                                 strcpy(curr_fil,mov_fil);
  388.                                 b=back_index(back,back_max,curr_adr,curr_fil,methode);         
  389.                                 if (!get_test_request)
  390.                                   has_been_moved = 1;       // sinon ne pas forcer has_been_moved car non dΘplacΘ
  391.                                 petits_tours++;
  392.                                 //
  393.                               } else {// sinon on fait rien et on s'en va.. (ftp etc)
  394.                                 if ( (opt->debug>1)  && (opt->errlog)) {
  395.                                   fspc(opt->errlog,"debug"); fprintf(opt->errlog,"Warning: Savename redirect backing error at %s%s"LF,mov_adr,mov_fil);
  396.                                   test_flush;
  397.                                 } 
  398.                               }
  399.                             }
  400.                           } else {
  401.                             if ( opt->errlog!=NULL ) {
  402.                               fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop to same filename)"LF,adr_complete,fil_complete);
  403.                               test_flush;
  404.                             }
  405.                           }
  406.                           
  407.                         }
  408.                       }
  409.                     } else{  // arrΩter les frais
  410.                       if ( opt->errlog!=NULL ) {
  411.                         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop)"LF,adr_complete,fil_complete);
  412.                         test_flush;
  413.                       }
  414.                     }
  415.                   }  // ok, leaving
  416.                 }
  417.                 
  418.               } while(back[b].status>0);
  419.               
  420.               // Si non dΘplacΘ, forcer type?
  421.               if (!has_been_moved) {
  422.                 if (back[b].r.statuscode!=-10) {    // erreur
  423.                   if (strnotempty(back[b].r.contenttype)==0)
  424.                     strcpy(back[b].r.contenttype,"text/html");    // message d'erreur en html
  425.                   // Finalement on, renvoie un erreur, pour ne toucher α rien dans le code
  426.                   // libΘrer emplacement backing
  427.                   /*if (opt->errlog!=NULL) {
  428.                     fspc(opt->errlog,0); fprintf(opt->errlog,"Error: (during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  429.                     test_flush;
  430.                   }                    
  431.                   back_delete(back,b);
  432.                   return -1;        // ERREUR (404 par exemple)
  433.                   */
  434.                 } 
  435.                 
  436.                 {            // pas d'erreur, changer type?
  437.                   char s[16]="";
  438.                   if (strnotempty(back[b].r.cdispo)) {        /* filename given */
  439.                     ext_chg=2;      /* change filename */
  440.                     strcpy(ext,back[b].r.cdispo);
  441.                   }
  442.                   else if ((!may_unknown(back[b].r.contenttype)) || (!get_ext(back[b].url_fil)) ) {  // on peut patcher α priori? (pas interdit ou pas de type)
  443.                     give_mimext(s,back[b].r.contenttype);  // obtenir extension
  444.                     if (strnotempty(s)>0) {    // on a reconnu l'extension
  445.                       ext_chg=1;
  446.                       strcpy(ext,s);
  447.                     }
  448.                   }
  449.                 }
  450.               }
  451.               // FIN Si non dΘplacΘ, forcer type?
  452.  
  453.               // libΘrer emplacement backing
  454.               back_delete(back,b);
  455.               
  456.               // --- --- ---
  457.               // oops, a ΘtΘ dΘplacΘ.. on recalcule en rΘcursif (osons!)
  458.               if (has_been_moved) {
  459.                 // copier adr, fil (optionnel, mais sinon marche pas pour le rip)
  460.                 strcpy(adr_complete,curr_adr);
  461.                 strcpy(fil_complete,curr_fil);
  462.                 // copier adr, fil
  463.                 
  464.                 return url_savename(curr_adr,curr_fil,save,NULL,NULL,referer_adr,referer_fil,opt,liens,lien_tot,back,back_max,cache,hash,ptr,numero_passe);
  465.               }
  466.               // --- --- ---
  467.               
  468.             }
  469.             
  470.           } else {
  471.             printf("PANIC! : Savename Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  472. #if BDEBUG==1
  473.             printf("error while savename crash adding\n");
  474. #endif
  475.             if (opt->errlog) {
  476.               fspc(opt->errlog,"error"); fprintf(opt->errlog,"Unexpected savename backing error at %s%s"LF,adr,fil_complete);
  477.               test_flush;
  478.             } 
  479.             
  480.           }
  481.           // restaurer
  482. #if HTS_ANALYSTE==2
  483.           _hts_in_html_parsing=hihp;
  484. #endif
  485.         }  // cachΘ?
  486.       }
  487.     }
  488.   }
  489.  
  490.  
  491.  
  492.   // - - - DEBUT NOMMAGE - - -
  493.  
  494.   // Donner nom par dΘfaut?
  495.   if (fil[strlen(fil)-1]=='/')  {
  496.     if (strncmp(adr_complete,"ftp://",6))
  497.       strcat(fil,DEFAULT_HTML);     // nommer page par dΘfaut!!
  498.     else {
  499.       if (!opt->proxy.active)
  500.         strcat(fil,DEFAULT_FTP);     // nommer page par dΘfaut (texte)
  501.       else
  502.         strcat(fil,DEFAULT_HTML);     // nommer page par dΘfaut (α priori ici html depuis un proxy http)
  503.     }
  504.   }
  505.   // Changer extension?
  506.   // par exemple, php3 sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  507.   if (ext_chg) {  // changer ext
  508.     char* a=fil+strlen(fil)-1;
  509.     if ( (opt->debug>1) && (opt->log!=NULL) ) {
  510.       fspc(opt->log,"debug");
  511.       if (ext_chg==1)
  512.         fprintf(opt->log,"Changing link extension %s%s to .%s"LF,adr_complete,fil_complete,ext);
  513.       else
  514.         fprintf(opt->log,"Changing link name %s%s to %s"LF,adr_complete,fil_complete,ext);
  515.       test_flush;
  516.     }
  517.     if (ext_chg==1) {
  518.       while(((int) a>(int) fil) && (*a!='.') && (*a!='/')) a--;
  519.       if (*a=='.') *a='\0';  // couper
  520.       strcat(fil,".");      // recopier point
  521.     } else {
  522.       while(((int) a>(int) fil) && (*a!='/')) a--;
  523.       if (*a=='/') a++;
  524.       *a='\0';
  525.    }
  526.     strcat(fil,ext);    // copier ext/nom
  527.   }
  528.  
  529.   // Rechercher premier / et dernier .
  530.   {  
  531.     char* a=fil+strlen(fil)-1;
  532.  
  533.     // passer structures
  534.     start_pos=fil;
  535.     while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) {
  536.       if (*a == '.')    // point? noter position
  537.         if (!dot_pos)
  538.           dot_pos=a;
  539.         a--;
  540.     }
  541.     if ((*a=='/') || (*a=='\\')) a++;
  542.     nom_pos = a;
  543.   }
  544.  
  545.   
  546.   // un nom de fichier est gΘnΘrΘ
  547.   // s'il existe dΘja, alors on le mofifie lΘgΦrement
  548.  
  549.   // ajouter nom du site Θventuellement en premier
  550.   if (opt->savename_type == -1) {    // utiliser savename_userdef! (%h%p/%n%q.%t)
  551.     char* a = opt->savename_userdef;
  552.     char* b = save;
  553.     /*char *nom_pos=NULL,*dot_pos=NULL;  // Position nom et point */
  554.     char tok;
  555.  
  556.     /*
  557.     {  // Rechercher premier /
  558.       char* a=fil+strlen(fil)-1;
  559.       // passer structures
  560.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) {
  561.         if (*a == '.')    // point? noter position
  562.         if (!dot_pos)
  563.           dot_pos=a;
  564.         a--;
  565.       }
  566.       if ((*a=='/') || (*a=='\\')) a++;
  567.       nom_pos = a;
  568.     }
  569.     */
  570.  
  571.     // Construire nom
  572.     while ((*a) && (((int) b - (int) save) < 800 ) ) {    // parser, et pas trop long..
  573.       if (*a == '%') {
  574.         int short_ver=0;
  575.         a++;
  576.         if (*a == 's') {
  577.           short_ver=1;
  578.           a++;
  579.         }
  580.         *b='\0';
  581.         switch(tok=*a++) {
  582.           case '[':            // %[param]
  583.             if (strchr(a,']')) {
  584.               char name[256];
  585.               char* c=name;
  586.               while(*a!=']') {
  587.                 *c++=*a++;
  588.               }
  589.               a++;
  590.               *c++='\0';
  591.               strcat(name,"=");           /* param=.. */
  592.               c=strchr(fil_complete,'?');
  593.               /* parameters exists */
  594.               if (c) {
  595.                 c=strstr(c,name);     /* finds param= */
  596.                 if (c) {
  597.                   c+=strlen(name);    /* jumps "param=" */
  598.                   while( (*c) && (*c!='&'))
  599.                     *b++=*c++;
  600.                 }
  601.               }
  602.             }
  603.           break;
  604.           case '%': *b++='%'; break;
  605.           case 'n':    // nom sans ext
  606.             if (dot_pos) {
  607.               if (!short_ver)    // Noms longs
  608.                 strncat(b,nom_pos,(int) dot_pos - (int) nom_pos);
  609.               else
  610.                 strncat(b,nom_pos,min((int) dot_pos - (int) nom_pos,8));
  611.             } else {
  612.               if (!short_ver)    // Noms longs
  613.                 strcpy(b,nom_pos);
  614.               else
  615.                 strncat(b,nom_pos,8);
  616.             }
  617.             b+=strlen(b);   // pointer α la fin
  618.             break;
  619.           case 'N':    // nom avec ext
  620.             // RECOPIE NOM + EXT
  621.             *b='\0';
  622.             if (dot_pos) {
  623.               if (!short_ver)    // Noms longs
  624.                 strncat(b,nom_pos,(int) dot_pos - (int) nom_pos);
  625.               else
  626.                 strncat(b,nom_pos,min((int) dot_pos - (int) nom_pos,8));
  627.             } else {
  628.               if (!short_ver)    // Noms longs
  629.                 strcpy(b,nom_pos);
  630.               else
  631.                 strncat(b,nom_pos,8);
  632.             }
  633.             b+=strlen(b);   // pointer α la fin
  634.             // RECOPIE NOM + EXT
  635.             *b='\0';
  636.             if (dot_pos) {
  637.               if (!short_ver)    // Noms longs
  638.                 strcpy(b,dot_pos+1);
  639.               else
  640.                 strncat(b,dot_pos+1,3);
  641.             } else {
  642.               if (!short_ver)    // Noms longs
  643.                 strcpy(b,DEFAULT_EXT);    // pas de..
  644.               else
  645.                 strcpy(b,DEFAULT_EXT_SHORT);    // pas de..
  646.             }
  647.             b+=strlen(b);   // pointer α la fin
  648.             //
  649.             break;
  650.           case 't':    // ext
  651.             *b='\0';
  652.             if (dot_pos) {
  653.               if (!short_ver)    // Noms longs
  654.                 strcpy(b,dot_pos+1);
  655.               else
  656.                 strncat(b,dot_pos+1,3);
  657.             } else {
  658.               if (!short_ver)    // Noms longs
  659.                 strcpy(b,DEFAULT_EXT);    // pas de..
  660.               else
  661.                 strcpy(b,DEFAULT_EXT_SHORT);    // pas de..
  662.             }
  663.             b+=strlen(b);   // pointer α la fin
  664.             break;
  665.           case 'p':    // path sans dernier /
  666.             *b='\0';
  667.             if (nom_pos != fil + 1) { // pas: /index.html (chemin nul)
  668.               if (!short_ver) {   // Noms longs
  669.                 strncat(b,fil,(int) nom_pos - (int) fil - 1);
  670.               } else {
  671.                 char pth[HTS_URLMAXSIZE*2],n83[HTS_URLMAXSIZE*2];
  672.                 pth[0]=n83[0]='\0';
  673.                 //
  674.                 strncat(pth,fil,(int) nom_pos - (int) fil - 1);
  675.                 long_to_83(n83,pth);
  676.                 strcpy(b,n83);
  677.               }
  678.             }
  679.             b+=strlen(b);   // pointer α la fin
  680.             break;
  681.           case 'h':    // host
  682.             *b='\0';
  683.             if (strcmp(adr_complete,"file://")==0) {
  684.               if (!short_ver)    // Noms longs
  685.                 strcpy(b,"localhost");
  686.               else
  687.                 strcpy(b,"local");
  688.             } else {
  689.               if (!short_ver)    // Noms longs
  690.                 strcpy(b,print_adr);
  691.               else
  692.                 strncat(b,print_adr,8);
  693.             }
  694.             b+=strlen(b);   // pointer α la fin
  695.             break;
  696.           case 'M':         /* host/address?query MD5 (128-bits) */
  697.             *b='\0';
  698.             {
  699.               char digest[32+2];
  700.               char buff[HTS_URLMAXSIZE*2];
  701.               digest[0]=buff[0]='\0';
  702.               strcpy(buff,adr);
  703.               strcat(buff,fil_complete);
  704.               domd5mem(buff,strlen(buff),digest,1,0);
  705.               strcpy(b,digest);
  706.             }
  707.             b+=strlen(b);   // pointer α la fin
  708.             break;
  709.           case 'Q': case 'q':         /* query MD5 (128-bits/16-bits) 
  710.                                          GENERATED ONLY IF query string exists! */
  711.             *b='\0';
  712.             strncat(b,url_md5(fil_complete),(tok == 'Q')?32:4);
  713.             b+=strlen(b);   // pointer α la fin
  714.             break;
  715.         }
  716.       } else
  717.         *b++=*a++;
  718.     }
  719.     *b++='\0';
  720.     //
  721.     // Types prΘdΘfinis
  722.     //
  723.  
  724.   } 
  725.   //
  726.   // Structure originale
  727.   else if (opt->savename_type%100==0) { 
  728.     /* recopier www.. */
  729.     if (opt->savename_type!=100) {  
  730.       if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  731.         if (strcmp(adr_complete,"file://")==0) {
  732.           //## if (*adr==lOCAL_CHAR) {
  733.           if (!opt->savename_83)  // noms longs
  734.             strcat(save,"localhost");
  735.           else
  736.             strcat(save,"local");
  737.         } else {
  738.           // adresse url
  739.           if (!opt->savename_83) {  // noms longs
  740.             strcat(save,print_adr);
  741.           } else {  // noms 8-3
  742.             if (strlen(print_adr)>4) {
  743.               if (strfield(print_adr,"www."))
  744.                 strncat(save,print_adr+4,8);
  745.               else
  746.                 strncat(save,print_adr,8);
  747.             } else strncat(save,print_adr,8);
  748.           }
  749.         }
  750.         if (*fil!='/') strcat(save,"/");
  751.       }
  752.     }
  753.   
  754. #if HTS_CASSE==0
  755.     hts_lowcase(save);
  756. #endif  
  757.         
  758.     /*
  759.     // ne sert α rien car a dΘja ΘtΘ filtrΘ normalement
  760.     if ((*fil=='.') && (*(fil+1)=='/'))          // ./index.html ** //
  761.       url_savename_addstr(save,fil+2);
  762.     else                                               // index.html ou /index.html
  763.       url_savename_addstr(save,fil);
  764.     if (save[strlen(save)-1]=='/') 
  765.       strcat(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  766. */
  767.  
  768.     /* add name */
  769.     ADD_STANDARD_PATH;
  770.     ADD_STANDARD_NAME(0);
  771.  
  772.   }
  773.   //
  774.   // Structure html/image
  775.   else {    
  776.     // dossier "web" ou "www.xxx" ?
  777.     if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  778.       if ((opt->savename_type/100)%2) {
  779.         if (strcmp(adr_complete,"file://")==0) {
  780.         //## if (*adr==lOCAL_CHAR) {
  781.           if (!opt->savename_83)  // noms longs
  782.             strcat(save,"localhost/");
  783.           else
  784.             strcat(save,"local/");
  785.         } else {
  786.           // adresse url
  787.           if (!opt->savename_83) {  // noms longs
  788.             strcat(save,print_adr); strcat(save,"/");
  789.           } else {  // noms 8-3
  790.             if (strlen(print_adr)>4) {
  791.               if (strfield(print_adr,"www."))
  792.                 strncat(save,print_adr+4,8);
  793.               else
  794.                 strncat(save,print_adr,8);
  795.               strcat(save,"/");
  796.             } else { 
  797.               strncat(save,print_adr,8); strcat(save,"/");
  798.             }
  799.           }
  800.         }
  801.       } else {
  802.         strcat(save,"web/");    // rΘpertoire gΘnΘral
  803.       }
  804.     } 
  805.  
  806.     // si un html α coup s√r
  807.     if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  808.       if (opt->savename_type%100==2) {  // html/
  809.         strcat(save,"html/");
  810.       }
  811.     } else {
  812.       if ((opt->savename_type%100==1) || (opt->savename_type%100==2)) {  // html & images
  813.         strcat(save,"images/");
  814.       }
  815.     }
  816.     
  817.     switch (opt->savename_type%100) {
  818.     case 4: case 5: {           // sΘparer par types
  819.       char* a=fil+strlen(fil)-1;
  820.       // passer structures
  821.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) a--;      
  822.       if ((*a=='/') || (*a=='\\')) a++;
  823.  
  824.       // html?
  825.       if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  826.         if (opt->savename_type%100==5)
  827.           strcat(save,"html/");
  828.       } else {
  829.         char* a=fil+strlen(fil)-1;
  830.         while(((int) a>(int) fil) && (*a != '/') && (*a != '.')) a--;      
  831.         if (*a!='.')
  832.           strcat(save,"other");
  833.         else
  834.           strcat(save,a+1);
  835.         strcat(save,"/");
  836.       }
  837.       /*strcat(save,a);*/
  838.       /* add name */
  839.       ADD_STANDARD_NAME(0);
  840.             }
  841.       break;
  842.     case 99: {                  // 'codΘ' .. c'est un gadget
  843.       int i;
  844.       int j;
  845.       char* a;
  846.       char C[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
  847.       int L;
  848.       // pseudo-CRC sur fil et adr pour initialiser gΘnΘrateur alΘatoire..
  849.       unsigned int s=0;
  850.       L=strlen(C);
  851.       for(i=0;i<(int) strlen(fil_complete);i++) {
  852.         s+=(unsigned int) fil_complete[i];
  853.       }
  854.       for(i=0;i<(int) strlen(adr_complete);i++) {
  855.         s+=(unsigned int) adr_complete[i];
  856.       }
  857.       srand(s);
  858.       
  859.       j=strlen(save);
  860.       for(i=0;i<8;i++) {
  861.         char c=C[(rand()%L)];
  862.         save[i+j]=c;
  863.       }
  864.       save[i+j]='\0';
  865.       // ajouter extension
  866.       a=fil+strlen(fil)-1;
  867.       while(((int) a>(int) fil) && (*a != '/') && (*a != '.')) a--;
  868.       if (*a=='.') {
  869.         strcat(save,a);    // ajouter
  870.       }
  871.              } 
  872.       break;
  873.     default: {   // noms sans les noms des rΘpertoires
  874.       // ne garder que le nom, pas la structure
  875.       /*
  876.       char* a=fil+strlen(fil)-1;
  877.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) a--;      
  878.       if ((*a=='/') || (*a=='\\')) a++;
  879.       strcat(save,a);
  880.       */
  881.  
  882.       /* add name */
  883.       ADD_STANDARD_NAME(0);
  884.             }
  885.       break;
  886.     }
  887.  
  888. #if HTS_CASSE==0
  889.     hts_lowcase(save);
  890. #endif  
  891.  
  892.     if (save[strlen(save)-1]=='/') 
  893.       strcat(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  894.   }
  895.  
  896.  
  897.   // vΘrifier qu'on ne doit pas forcer l'extension
  898.   // par exemple, asp sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  899.   /*if (ext_chg) {
  900.     char* a=save+strlen(save)-1;
  901.     while(((int) a>(int) save) && (*a!='.') && (*a!='/')) a--;
  902.     if (*a=='.') *a='\0';  // couper
  903.     // recopier extension
  904.     strcat(save,".");
  905.     strcat(save,ext);    // copier ext
  906.   }*/
  907.   // de mΩme en cas de manque d'extension on en place une de maniΦre forcΘe..
  908.   // cela Θvite les /chez/toto et les /chez/toto/index.html incompatibles
  909.   if (opt->savename_type != -1) {
  910.     char* a=save+strlen(save)-1;
  911.     while(((int) a>(int) save) && (*a!='.') && (*a!='/')) a--;
  912.     if (*a!='.') {   // agh pas de point
  913.       //strcat(save,".none");                 // a Θviter
  914.       strcat(save,".html");                   // prΘfΘrable!
  915.       if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  916.         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Default HTML type set for %s%s"LF,adr_complete,fil_complete);
  917.         test_flush;
  918.       }
  919.     }
  920.   }
  921.  
  922.   // effacer pass au besoin pour les autentifications
  923.   // (plus la peine : masquΘ au dΘbut)
  924. /*
  925.   {
  926.     char* a=jump_identification(save);
  927.     if (a!=save) {
  928.       char tempo[HTS_URLMAXSIZE*2];
  929.       char *b;
  930.       tempo[0]='\0';
  931.       strcpy(tempo,"[");
  932.       b=strchr(save,':');
  933.       if (!b) b=strchr(save,'@');
  934.       if (b)
  935.         strncat(tempo,save,(int) b-(int) a);
  936.       strcat(tempo,"]");
  937.       strcat(tempo,a);
  938.       strcpy(save,a);
  939.     }
  940.   }
  941. */
  942.  
  943.   // Θviter les / au dΘbut (cause: N100)
  944.   if (save[0]=='/') {
  945.     char tempo[HTS_URLMAXSIZE*2];
  946.     strcpy(tempo,save+1);
  947.     strcpy(save,tempo);
  948.   }
  949.  
  950.   // changer les ~,:,",*,? en _ pour sauver sur disque
  951.   hts_replace(save,'~','_');  // interdit sous unix (~foo)
  952.   //
  953.   hts_replace(save,'\\','_');
  954.   hts_replace(save,':','_');  // interdit sous windows
  955.   hts_replace(save,'*','_');  // interdit sous windows
  956.   hts_replace(save,'?','_');  // doit pas arriver!!
  957.   hts_replace(save,'\"','_');  // interdit sous windows
  958.   hts_replace(save,'<','_');  // interdit sous windows
  959.   hts_replace(save,'>','_');  // interdit sous windows
  960.   hts_replace(save,'|','_');  // interdit sous windows
  961.   //
  962.   hts_replace(save,'@','_');
  963.   //
  964.   { // Θliminer les // (comme ftp://)
  965.     char* a;
  966.     while( (a=strstr(save,"//")) ) *a='_';
  967.   }
  968.  
  969.    
  970. #if HTS_OVERRIDE_DOS_FOLDERS
  971.   /* Replace /foo/nul/bar by /foo/nul-/bar */
  972.   {
  973.     int i=0;
  974.     while(hts_tbdev[i][0]) {
  975.       char* a=save;
  976.       while((a=strstr(a,hts_tbdev[i]))) {
  977.         switch ( (int) a[strlen(hts_tbdev[i])] ) {
  978.         case '\0':
  979.         case '/':  {
  980.           char tempo[HTS_URLMAXSIZE*2]; tempo[0]='\0';
  981.           strncat(tempo,save,(int) a - (int) save + strlen(hts_tbdev[i]));
  982.           strcat(tempo,"-");
  983.           strcat(tempo,a+strlen(hts_tbdev[i]));
  984.           strcpy(save,tempo);
  985.                    }
  986.           break;
  987.         }
  988.         a+=strlen(hts_tbdev[i]);
  989.       }
  990.       i++;
  991.     }
  992.   }
  993. #endif
  994.  
  995.   // conversion 8-3 .. y compris pour les rΘpertoires
  996.   if (opt->savename_83) {
  997.     char n83[HTS_URLMAXSIZE*2];
  998.     long_to_83(n83,save);
  999.     strcpy(save,n83);
  1000.   }
  1001.  
  1002.  
  1003.   /* ensure that there is no ../ (potential vulnerability) */
  1004.   fil_simplifie(save);
  1005.  
  1006.   // chemin primaire Θventuel A METTRE AVANT
  1007.   if (strnotempty(opt->path_html)) {
  1008.     char tempo[HTS_URLMAXSIZE*2];
  1009.     strcpy(tempo,opt->path_html);
  1010.     strcat(tempo,save);
  1011.     strcpy(save,tempo);
  1012.   }
  1013.  
  1014.  
  1015.   // vΘrifier que le nom n'est pas dΘja pris...
  1016.   if (liens!=NULL) { 
  1017.     int nom_ok;
  1018.     do {
  1019.       register int i;
  1020.       register int len;
  1021.       len=strlen(save);    // taille
  1022.       //
  1023.       nom_ok=1;  // α priori bon
  1024.       // on part de la fin pour optimiser, plus les opti de taille pour aller encore plus vite..
  1025. #if DEBUG_SAVENAME
  1026. printf("\nStart search\n");
  1027. #endif
  1028.  
  1029. #if HTS_HASH
  1030.       i=hash_read(hash,save,"",0);      // lecture type 0 (sav)
  1031.       if (i>=0)
  1032. #else
  1033.       for(i=lien_tot-1;i>=0;i--) {
  1034. #if DEBUG_SAVENAME
  1035. printf("%cParse: %d",13,i);
  1036. #endif
  1037.         
  1038.         if (liens[i]->sav_len==len) {    // mΩme taille de chaεne          
  1039. #if HTS_CASSE
  1040.           if (strcmp(liens[i]->sav,save)==0)    // existe dΘja
  1041. #else
  1042.           if (strfield2(liens[i]->sav,save))    // un tel nom existe dΘja
  1043. #endif
  1044. #endif
  1045.           {
  1046. #if HTS_CASSE
  1047.             if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  1048. #else
  1049.             if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  1050. #endif
  1051.             {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  1052.               //printf("Ok, %s\n",save);
  1053.               //i=lien_tot;    // sortir
  1054.               i=0;
  1055. #if DEBUG_SAVENAME
  1056. printf("\nOK ALREADY DEFINED\n",13,i);
  1057. #endif
  1058.             } else {  // utilisΘ par un AUTRE, changer de nom
  1059.               char tempo[HTS_URLMAXSIZE*2];
  1060.               char* a=save+strlen(save)-1;
  1061.               char* b;
  1062.               int n=2;       
  1063.               tempo[0]='\0';
  1064.  
  1065. #if DEBUG_SAVENAME
  1066. printf("\nWRONG CASE UNMATCH : \n%s\n%s, REDEFINE\n",liens[i]->fil,fil_complete);
  1067. #endif
  1068.               nom_ok=0;
  1069.               i=0;
  1070.               
  1071.               while(((int) a>(int) save) && (*a!='.') && (*a!='\\') && (*a!='/')) a--;
  1072.               if (*a=='.')
  1073.                 strncat(tempo,save,(int) a-(int) save);
  1074.               else
  1075.                 strcat(tempo,save);
  1076.               
  1077.               // tester la prΘsence d'un -xx (ex: index-2.html -> index-3.html)
  1078.               b=tempo+strlen(tempo)-1;
  1079.               while (isdigit((unsigned char)*b)) b--;
  1080.               if (*b=='-') {
  1081.                 sscanf(b+1,"%d",&n);
  1082.                 *b='\0';    // couper
  1083.                 n++;  // plus un
  1084.               }
  1085.               
  1086.               // en plus il faut gΘrer le 8-3 .. pas facile le client
  1087.               if (opt->savename_83) {
  1088.                 int max;
  1089.                 char* a=tempo+strlen(tempo)-1;
  1090.                 while(((int) a>(int) tempo) && (*a!='/')) a--;
  1091.                 if (*a=='/') a++;
  1092.                 max=8-1-nombre_digit(n);
  1093.                 if ((int) strlen(a)>max)
  1094.                   *(a+max)='\0';  // couper sinon il n'y aura pas la place!
  1095.               }
  1096.               
  1097.               // ajouter -xx (ex: index.html -> index-2.html)
  1098.               sprintf(tempo+strlen(tempo),"-%d",n);
  1099.               
  1100.               // ajouter extension
  1101.               if (*a=='.')
  1102.                 strcat(tempo,a);
  1103.               
  1104.               strcpy(save,tempo);
  1105.               
  1106.               //printf("switched: %s\n",save);
  1107.               
  1108.             }  // if
  1109. #if HTS_HASH
  1110.           }
  1111. #else
  1112.           }  // if
  1113.         }  // if sav_len
  1114.       }  // for
  1115. #endif
  1116. #if DEBUG_SAVENAME
  1117. printf("\nEnd search, %s\n",fil_complete);
  1118. #endif
  1119.     } while(!nom_ok);
  1120.     
  1121.   }
  1122.   
  1123.   //printf("'%s' %s %s\n",save,adr,fil);
  1124.       
  1125.   return 0;
  1126. }
  1127.  
  1128. /* nom avec md5 urilisΘ partout */
  1129. void standard_name(char* b,char* dot_pos,char* nom_pos,char* fil_complete,int short_ver) {
  1130.   b[0]='\0';
  1131.   /* Nom */
  1132.   if (dot_pos) {
  1133.     if (!short_ver)    // Noms longs
  1134.       strncat(b,nom_pos,(int) dot_pos - (int) nom_pos);
  1135.     else
  1136.       strncat(b,nom_pos,min((int) dot_pos - (int) nom_pos,8));
  1137.   } else {
  1138.     if (!short_ver)    // Noms longs
  1139.       strcat(b,nom_pos);
  1140.     else
  1141.       strncat(b,nom_pos,8);
  1142.   }
  1143.   /* MD5 - 16 bits */
  1144.   strncat(b,url_md5(fil_complete),4);
  1145.   /* Ext */
  1146.   if (dot_pos) {
  1147.     strcat(b,".");
  1148.     if (!short_ver)    // Noms longs
  1149.       strcat(b,dot_pos+1);
  1150.     else
  1151.       strncat(b,dot_pos+1,3);
  1152.   } else {
  1153.     if (!short_ver)    // Noms longs
  1154.       strcat(b,DEFAULT_EXT);    // pas de..
  1155.     else
  1156.       strcat(b,DEFAULT_EXT_SHORT);    // pas de..
  1157.   }
  1158. }
  1159.  
  1160.  
  1161. /* Petit md5 */
  1162. char* url_md5(char* fil_complete) {
  1163.   static char digest[32+2];
  1164.   char* a;
  1165.   digest[0]='\0';
  1166.   a=strchr(fil_complete,'?');
  1167.   if (a) {
  1168.     if (strlen(a)) {
  1169.       char buff[HTS_URLMAXSIZE*2];
  1170.       a++;
  1171.       digest[0]=buff[0]='\0';
  1172.       strcat(buff,a);         /* query string MD5 */
  1173.       domd5mem(buff,strlen(buff),digest,1,0);
  1174.     }
  1175.   }
  1176.   return digest;
  1177. }
  1178.  
  1179. // interne α url_savename: ajoute une chaεne α une autre avec \ -> /
  1180. void url_savename_addstr(char* d,char* s) {
  1181.   int i=strlen(d);
  1182.   while(*s) {
  1183.     if (*s=='\\')  // remplacer \ par des /
  1184.       d[i++]='/';
  1185.     else
  1186.       d[i++]=*s;
  1187.     s++;
  1188.   }
  1189.   d[i]='\0';
  1190. }
  1191.  
  1192. #undef test_flush
  1193.