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