home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / contrib / samba / samba-1.8 / samba-1 / samba-1.8.05 / mangle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-27  |  22.6 KB  |  809 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.8.
  4.    Copyright (C) Andrew Tridgell 1992,1993,1994
  5.    
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #include "includes.h"
  22. #include "loadparm.h"
  23.  
  24. extern int DEBUGLEVEL;
  25.  
  26.  
  27.  
  28. /****************************************************************************
  29. provide a checksum on a string
  30. ****************************************************************************/
  31. int str_checksum(char *s)
  32. {
  33.   int res = 0;
  34.   int c;
  35.   int i=0;
  36.   while (*s)
  37.     {
  38.       c = *s;
  39.       res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
  40.       s++; i++;
  41.     }
  42.   return(res);
  43. }
  44.  
  45. /****************************************************************************
  46. return True if a name is a special msdos reserved name
  47. ****************************************************************************/
  48. BOOL is_reserved_msdos(char *fname)
  49. {
  50.   char upperFname[13];
  51.   char *p;
  52.  
  53.   StrnCpy (upperFname, fname, 12);
  54.  
  55.   /* lpt1.txt and con.txt etc are also illegal */
  56.   p=strchr(upperFname,'.');
  57.   if (p)
  58.    *p='\0';
  59.   strupper (upperFname);
  60.   if ((strcmp(upperFname,"CLOCK$") == 0) ||
  61.     (strcmp(upperFname,"CON") == 0) ||
  62.     (strcmp(upperFname,"AUX") == 0) ||
  63.     (strcmp(upperFname,"COM1") == 0) ||
  64.     (strcmp(upperFname,"COM2") == 0) ||
  65.     (strcmp(upperFname,"COM3") == 0) ||
  66.     (strcmp(upperFname,"COM4") == 0) ||
  67.     (strcmp(upperFname,"LPT1") == 0) ||
  68.     (strcmp(upperFname,"LPT2") == 0) ||
  69.     (strcmp(upperFname,"LPT3") == 0) ||
  70.     (strcmp(upperFname,"NUL") == 0) ||
  71.     (strcmp(upperFname,"PRN") == 0))
  72.       return (True) ;
  73.  
  74.   return (False);
  75. }
  76.  
  77.  
  78. static BOOL valid_dos_char[256];
  79.  
  80. #define VALID_DOS_PCHAR(p) (valid_dos_char[*(unsigned char *)(p)])
  81.  
  82. /****************************************************************************
  83. initialise the valid dos char array
  84. ****************************************************************************/
  85. void valid_initialise(void)
  86. {
  87.   static BOOL initialised = False;    
  88.   int i;
  89.  
  90.   if (initialised)
  91.     return;
  92.  
  93.   for (i=0;i<128;i++)
  94.     valid_dos_char[i] = (isalnum(i) || strchr("._^$~!#%&-{}()@'`",i));
  95.   for (i=128;i<256;i++) 
  96.     valid_dos_char[i] = False;    
  97.   
  98.   /*    When the special char exists both cases, windows uses
  99.     the uppercase code for DOS filename */
  100.   
  101.   /* any code page, low and uppercase, valid for all DOS PC */
  102.   valid_dos_char[142] = True;     /* A trema      */
  103.   valid_dos_char[143] = True;     /* A o          */
  104.   valid_dos_char[144] = True;     /* E '          */
  105.   valid_dos_char[146] = True;     /* AE           */
  106.   valid_dos_char[153] = True;     /* O trema      */
  107.   valid_dos_char[154] = True;     /* U trema      */
  108.   valid_dos_char[165] = True;     /* N tilda      */
  109.   
  110.   /* any code page, valid for all PC */
  111.   valid_dos_char[128] = True;     /* C cedille    */
  112.   valid_dos_char[156] = True;     /* Pound        */
  113.   
  114.   /* code page 850 (most common)*/
  115.   valid_dos_char[183] = True;     /* A `     (WIN)*/
  116.   valid_dos_char[157] = True;     /* Phi     (WIN)*/
  117.   valid_dos_char[212] = True;     /* E`      (WIN)*/
  118.   
  119.   initialised = True;
  120. }
  121.  
  122. /****************************************************************************
  123. return True if a name is in 8.3 dos format
  124. ****************************************************************************/
  125. BOOL is_8_3(char *fname)
  126. {
  127.   extern int case_sensitivity;
  128.   int len = strlen(fname);
  129.   char *dot_pos = strchr(fname,'.');
  130.   int l;
  131.  
  132.   DEBUG(5,("checking %s for 8.3\n",fname));
  133.  
  134.   switch (case_sensitivity)
  135.     {
  136.     case CASE_LOWER:
  137.       if (strhasupper(fname)) return(False);
  138.       break;
  139.     case CASE_UPPER:
  140.       if (strhaslower(fname)) return(False);
  141.       break;
  142.     }
  143.  
  144.   /* can't be longer than 12 chars */
  145.   if (len == 0 || len > 12)
  146.     return(False);
  147.  
  148.   /* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */
  149.   if (is_reserved_msdos(fname))
  150.     return(False);
  151.  
  152.   /* can't contain invalid dos chars */
  153.   /* Windows use the ANSI charset.
  154.      But filenames are translated in the PC charset.
  155.      This Translation may be more or less relaxed depending
  156.      the Windows application. */
  157.  
  158.   /* %%% A nice improvment to name mangling would be to translate
  159.      filename to ANSI charset on the smb server host */
  160.  
  161.   {
  162.     char *p = fname;
  163.     valid_initialise();
  164.  
  165. #ifdef KANJI
  166.     dot_pos = 0;
  167.     while (*p)
  168.       {
  169.       if (is_shift_jis (*p)) {
  170.           p += 2;
  171.       } else if (is_kana (*p)) {
  172.           p ++;
  173.       } else {
  174.           if (*p == '.' && !dot_pos)
  175.           dot_pos = (char *) p;
  176.           if (!VALID_DOS_PCHAR(p))
  177.           return(False);
  178.           p++;
  179.       }
  180.       }      
  181. #else
  182.     while (*p)
  183.       {
  184.     if (!VALID_DOS_PCHAR(p))
  185.       return(False);
  186.     p++;
  187.       }      
  188. #endif /* KANJI */
  189.   }
  190.  
  191.   /* no dot and less than 9 means OK */
  192.   if (!dot_pos)
  193.     return(len <= 8);
  194.     
  195.   l = (dot_pos - fname);
  196.  
  197.   /* base must be at least 1 char except special cases . and .. */
  198.   if (l == 0)
  199.     return(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0);
  200.  
  201.   /* base can't be greater than 8 */
  202.   if (l > 8)
  203.     return(False);
  204.  
  205.   /* extension must be between 1 and 3 */
  206.   if ( (len - l < 2 ) || (len - l > 4) )
  207.     return(False);
  208.  
  209.   /* extension can't have a dot */
  210.   if ((dot_pos = strchr(dot_pos+1,'.')))
  211.     return(False);
  212.  
  213.   /* must be in 8.3 format */
  214.   return(True);
  215. }
  216.  
  217.  
  218.  
  219. /*
  220. keep a stack of name mangling results - just
  221. so file moves and copies have a chance of working
  222. */
  223. fstring *mangled_stack = NULL;
  224. int mangled_stack_size = 0;
  225. int mangled_stack_len = 0;
  226.  
  227. /****************************************************************************
  228. create the mangled stack
  229. ****************************************************************************/
  230. void create_mangled_stack(int size)
  231. {
  232.   if (mangled_stack)
  233.     {
  234.       free(mangled_stack);
  235.       mangled_stack_size = 0;
  236.       mangled_stack_len = 0;
  237.     }
  238.   if (size > 0)
  239.     mangled_stack = (fstring *)malloc(sizeof(fstring)*size);
  240.   if (mangled_stack) mangled_stack_size = size;
  241. }
  242.  
  243. /****************************************************************************
  244. push a mangled name onto the stack
  245. ****************************************************************************/
  246. void push_mangled_name(char *s)
  247. {
  248.   int i;
  249.   char *p;
  250.  
  251.   if (!mangled_stack)
  252.     return;
  253.  
  254.   for (i=0;i<mangled_stack_len;i++)
  255.     if (strcmp(s,mangled_stack[i]) == 0)
  256.       {
  257.     array_promote(mangled_stack[0],sizeof(fstring),i);    
  258.     return;
  259.       }
  260.  
  261.   safe_memcpy(mangled_stack[1],mangled_stack[0],
  262.           sizeof(fstring)*MIN(mangled_stack_len,mangled_stack_size-1));
  263.   strcpy(mangled_stack[0],s);
  264.   p = strrchr(mangled_stack[0],'.');
  265.   if (p && (!strhasupper(p+1)) && (strlen(p+1) < 4))
  266.     *p = 0;
  267.   mangled_stack_len = MIN(mangled_stack_size,mangled_stack_len+1);
  268. }
  269.  
  270. /****************************************************************************
  271. check for a name on the mangled name stack
  272. ****************************************************************************/
  273. BOOL check_mangled_stack(char *s, char *MangledMap)
  274. {
  275.   int i;
  276.   pstring tmpname;
  277.   char extension[5]="";
  278.   char *p = strrchr(s,'.');
  279.   BOOL check_extension = False;
  280.  
  281.   if (!mangled_stack) return(False);
  282.  
  283.   if (p)
  284.     {
  285.       check_extension = True;
  286.       StrnCpy(extension,p,4);
  287.       strlower(extension);
  288.     }
  289.  
  290.   for (i=0;i<mangled_stack_len;i++)
  291.     {
  292.       strcpy(tmpname,mangled_stack[i]);
  293.       mangle_name_83(tmpname, MangledMap);
  294.       if (strcmp(tmpname,s) == 0)
  295.     {
  296.       strcpy(s,mangled_stack[i]);
  297.       break;
  298.     }
  299.       if (check_extension && !strchr(mangled_stack[i],'.'))
  300.     {
  301.       strcpy(tmpname,mangled_stack[i]);
  302.       strcat(tmpname,extension);
  303.       mangle_name_83(tmpname, MangledMap);
  304.       if (strcmp(tmpname,s) == 0)
  305.         {
  306.           strcpy(s,mangled_stack[i]);
  307.           strcat(s,extension);
  308.           break;
  309.         }      
  310.     }
  311.     }
  312.  
  313.   if (i < mangled_stack_len)
  314.     {
  315.       DEBUG(3,("Found %s on mangled stack as %s\n",s,mangled_stack[i]));
  316.       array_promote(mangled_stack[0],sizeof(fstring),i);
  317.       return(True);      
  318.     }
  319.  
  320.   return(False);
  321. }    
  322.  
  323. /****************************************************************************
  324. search for a name in a directory which when 83 mangled gives the specified
  325. string
  326. ****************************************************************************/
  327. void mangle_search_83(char *s,char *home,char *dir, char *MangledMap)
  328. {
  329.   void *dirptr;
  330.   struct DIRECT *dptr;
  331.   pstring tmpname="";
  332.  
  333.   DEBUG(3,("mangle search - searching for %s in %s\n",s,dir));
  334.  
  335.   if (check_mangled_stack(s, MangledMap))
  336.     return;
  337.  
  338.   strcpy(tmpname,home);
  339.   if (home[strlen(home)-1] != '/' && *dir != '/')
  340.     strcat(tmpname,"/");
  341.   strcat(tmpname,dir);
  342.   if (tmpname[strlen(tmpname)-1] == '/')
  343.     strcat(tmpname,".");
  344.  
  345.   dirptr = (void *)opendir(tmpname);
  346.  
  347.   if (!dirptr)
  348.     return;
  349.  
  350.   dptr = readdir(dirptr);
  351.   while (dptr)
  352.     {
  353.       strcpy(tmpname,dptr->d_name);
  354.       mangle_name_83(tmpname, MangledMap);
  355.       DEBUG(5,("Mangle: Trying %s gave %s\n",dptr->d_name,tmpname));
  356.       if (strcmp(tmpname,s) == 0)
  357.     {
  358.       strcpy(s,dptr->d_name);
  359.       push_mangled_name(s);
  360.       closedir(dirptr);
  361.       return;
  362.     }
  363.       dptr = readdir(dirptr);
  364.     }
  365.   
  366.   /* didn't find it */
  367.   strnorm(s);
  368.  
  369.   closedir(dirptr);
  370. }
  371.  
  372.  
  373. static char *mangled_match(char *s, /* This is null terminated */
  374.                            char *pattern, /* This isn't. */
  375.                            int len) /* This is the length of pattern. */
  376. {
  377.   static pstring matching_bit;  /* The bit of the string which matches */
  378.                                 /* a * in pattern if indeed there is a * */
  379.   char *sp;                     /* Pointer into s. */
  380.   char *pp;                     /* Pointer into p. */
  381.   char *match_start;            /* Where the matching bit starts. */
  382.   pstring pat;
  383.  
  384.   StrnCpy(pat, pattern, len);   /* Get pattern into a proper string! */
  385.   strcpy(matching_bit,"");      /* Match but no star gets this. */
  386.   pp = pat;                     /* Initialise the pointers. */
  387.   sp = s;
  388.   if ((len == 1) && (*pattern == '*')) {
  389.     return NULL;                /* Impossible, too ambiguous for */
  390.                                 /* words! */
  391.   }
  392.  
  393.   while ((*sp)                  /* Not the end of the string. */
  394.          && (*pp)               /* Not the end of the pattern. */
  395.          && (*sp == *pp)        /* The two match. */
  396.          && (*pp != '*')) {     /* No wildcard. */
  397.     sp++;                       /* Keep looking. */
  398.     pp++;
  399.   }
  400.   if (!*sp && !*pp)             /* End of pattern. */
  401.     return matching_bit;        /* Simple match.  Return empty string. */
  402.   if (*pp == '*') {
  403.     pp++;                       /* Always interrested in the chacter */
  404.                                 /* after the '*' */
  405.     if (!*pp) {                 /* It is at the end of the pattern. */
  406.       StrnCpy(matching_bit, s, sp-s);
  407.       return matching_bit;
  408.     } else {
  409.       /* The next character in pattern must match a character further */
  410.       /* along s than sp so look for that character. */
  411.       match_start = sp;
  412.       while ((*sp)              /* Not the end of s. */
  413.              && (*sp != *pp))   /* Not the same  */
  414.         sp++;                   /* Keep looking. */
  415.       if (!*sp) {               /* Got to the end without a match. */
  416.         return NULL;
  417.       } else {                  /* Still hope for a match. */
  418.         /* Now sp should point to a matching character. */
  419.         StrnCpy(matching_bit, match_start, sp-match_start);
  420.         /* Back to needing a stright match again. */
  421.         while ((*sp)            /* Not the end of the string. */
  422.                && (*pp)         /* Not the end of the pattern. */
  423.                && (*sp == *pp)) { /* The two match. */
  424.           sp++;                 /* Keep looking. */
  425.           pp++;
  426.         }
  427.         if (!*sp && !*pp)       /* Both at end so it matched */
  428.           return matching_bit;
  429.         else
  430.           return NULL;
  431.       }
  432.     }
  433.   }
  434.   return NULL;                  /* No match. */
  435. }
  436.  
  437. static BOOL do_rev_mangled_map(char *s, char *MangledMap)
  438. {
  439.   /* Does the reverse of do_fwd_mangled_map().  Look in there for
  440.    * details.
  441.    */
  442.   /* Look for the start and end of each of the mapping strings using
  443.    * these...
  444.    */
  445.   char *start_first=MangledMap;
  446.   char *end_first;
  447.   char *start_second=MangledMap;
  448.   char *end_second;
  449.   char *match_string;
  450.   char *ss;                     /* Pointer into s. */
  451.   char *pp;                     /* Pointer into pattern. */
  452.   pstring pattern;
  453.  
  454.   DEBUG(5,("Mangled Mapping '%s' map '%s'\n", s, MangledMap));
  455.   while (*start_first) {
  456.     while ((*start_first) && (*start_first != '('))
  457.       start_first++;
  458.     start_first++;              /* Skip the ( */
  459.     if (!*start_first)
  460.       continue;                 /* Always check for the end. */
  461.     end_first = start_first;    /* Search for the ' ' or a ')' */
  462.     DEBUG(5,("Start of first in pair '%s'\n", start_first));
  463.     while ((*end_first) && !((*end_first == ' ') || (*end_first == ')')))
  464.       end_first++;
  465.     if (!*end_first) {
  466.       start_first = end_first;
  467.       continue;                 /* Always check for the end. */
  468.     }
  469.     DEBUG(5,("End of first in pair '%s'\n", end_first));
  470.     /* Now look for the second pair. */
  471.     start_second = end_first+1; /* Point to start of second string in */
  472.                                 /* pair. */
  473.     DEBUG(5,("Start of second in pair '%s'\n", start_second));
  474.     end_second = start_second;
  475.     /* Find the end of the second of the pair. */
  476.     while ((*end_second) && (*end_second != ')'))
  477.       end_second++;
  478.     if (!*end_second) {
  479.       start_first = end_second;
  480.       continue;               /* Always check for the end. */
  481.     }
  482.     DEBUG(5,("End of second in pair '%s'\n", end_second));
  483.     if ((match_string=mangled_match(s, start_second, end_second-start_second)))
  484.       {
  485.     DEBUG(5,("Found a match\n"));
  486.     /* Substitute with the new name. */
  487.     ss = s;
  488.     StrnCpy(pattern, start_first, end_first-start_first);
  489.     pp = pattern;
  490.     while ((*pp)              /* Not end of pattern. */
  491.            && (*pp != '*'))   /* Not the wild bit. */
  492.       *ss++ = *pp++;
  493.     if (!*pp) {               /* The end of the pattern. */
  494.       DEBUG(5,("s is now '%s'\n", s));
  495.       return True;
  496.     }
  497.     /* Must have hit a star. */
  498.     pp++;                     /* Skip the star. */
  499.     strcat(ss, match_string); /* Bung in the matching bit. */
  500.     ss += strlen(match_string);
  501.     while ((*ss++ = *pp++))     /* Not end of pattern. */
  502.       ;
  503.     DEBUG(5,("s is now '%s'\n", s));
  504.     return True;              /* DONE! */
  505.     } else {
  506.       start_first = end_second; /* Skip a bit which cannot be wanted */
  507.       /* anymore. */
  508.     }
  509.     start_first++;
  510.   }
  511.   return False;
  512. }
  513.  
  514. /* this is the magic char used for mangling */
  515. char magic_char = '~';
  516.  
  517. /****************************************************************************
  518. convert a dos name to a unix name - possibly unmangling
  519. ****************************************************************************/
  520. void unix_convert_83(char *s,char *home,BOOL mangle, char *MangledMap)
  521. {
  522.   char *p;
  523.   unix_format(s);
  524.  
  525.   strnorm(s);
  526.  
  527.   if (!mangle) 
  528.     return;
  529.  
  530.   if (MangledMap && *MangledMap) {
  531.     /* I now have to scan the components of this file path to see if */
  532.     /* they need to be reversed mapped. */
  533.     char *d;                    /* Destination string pointer. */
  534.     char *start;
  535.     pstring component="";
  536.     p = s;                      /* Use p to scan the string. */
  537.  
  538.     while (*p) {
  539.       if ((*p == '/') || (p == s)) { /* Path separator or start of string. */
  540.         if (*p == '/')
  541.           p++;                  /* get to the name bit. */
  542.         start = p;              /* And remember its start position. */
  543.         d = component;
  544.         while (*p && (*p != '/')) /* And copy it into component. */
  545.           *d++ = *p++;
  546.         *d++ = '\0';
  547.         if (do_rev_mangled_map(component, MangledMap)) {
  548.           pstring new_s;
  549.           StrnCpy(new_s, s, start-s);
  550.           strcat(new_s, component);
  551.           strcat(new_s, p);
  552.           strcpy(s, new_s);
  553.           p = start + strlen(component);
  554.         }
  555.       } else {
  556.         p++;                    /* I shouldn't get here. */
  557.       }
  558.     }
  559.   }
  560.  
  561.   DEBUG(5,("Converting name %s ",s));
  562.  
  563.   unix_clean_name(s);
  564.  
  565.   /* Now need to do a reverse lookup in MangledMap as I will have got
  566.    * the second of the pair from the client and I want to map to the
  567.    * first.
  568.    */
  569.  
  570.   while ((p = strchr(s,magic_char)))
  571.     {
  572.       char *p2;
  573.  
  574.       pstring directory="";
  575.       pstring name="";
  576.       pstring rest="";
  577.  
  578.       /* pull off the rest of the name */      
  579.       if ((p2 = strchr(p,'/')))
  580.     {
  581.       *p2 = 0;
  582.       strcpy(rest,p2+1);
  583.     }
  584.  
  585.       /* pull out the name itself */
  586.       if ((p2 = strrchr(s,'/')))
  587.     {
  588.       *p2 = 0;
  589.       strcpy(name,p2+1);
  590.       strcpy(directory,s);
  591.     }
  592.       else
  593.     strcpy(name,s);
  594.  
  595.       strupper(name);
  596.       /* now search through the directory for a matching name */
  597.       mangle_search_83(name,home,directory, MangledMap);
  598.       string_replace(name,magic_char,1);
  599.  
  600.       /* and construct the name again */
  601.       strcpy(s,directory);
  602.       if (*directory)
  603.     strcat(s,"/");
  604.       strcat(s,name);
  605.       if (*rest)
  606.     strcat(s,"/");
  607.       strcat(s,rest);
  608.     }
  609.   string_replace(s,1,magic_char);
  610.   DEBUG(5,("to %s\n",s));
  611. }
  612.  
  613. /****************************************************************************
  614. return a base 36 character. v must be from 0 to 35.
  615. ****************************************************************************/
  616. char base36(int v)
  617. {
  618.   v = v % 36;
  619.   if (v < 10)
  620.     return('0'+v);
  621.   return('A' + (v-10));
  622. }
  623.  
  624. static BOOL do_fwd_mangled_map(char *s, char *MangledMap)
  625. {
  626.   /* MangledMap is a series of name pairs in () separated by spaces.
  627.    * If s matches the first of the pair then the name given is the
  628.    * second of the pair.  A * means any number of any character and if
  629.    * present in the second of the pair as well as the first the
  630.    * matching part of the first string takes the place of the * in the
  631.    * second.
  632.    *
  633.    * I wanted this so that we could have RCS files which can be used
  634.    * by UNIX and DOS programs.  My mapping string is (RCS rcs) which
  635.    * converts the UNIX RCS file subdirectory to lowercase thus
  636.    * preventing mangling.
  637.    */
  638.   char *start=MangledMap;       /* Use this to search for mappings. */
  639.   char *end;                    /* Used to find the end of strings. */
  640.   char *match_string;
  641.   pstring new_string;           /* Make up the result here. */
  642.   char *np;                     /* Points into new_string. */
  643.  
  644.   DEBUG(5,("Mangled Mapping '%s' map '%s'\n", s, MangledMap));
  645.   while (*start) {
  646.     while ((*start) && (*start != '('))
  647.       start++;
  648.     start++;                    /* Skip the ( */
  649.     if (!*start)
  650.       continue;                 /* Always check for the end. */
  651.     end = start;                /* Search for the ' ' or a ')' */
  652.     DEBUG(5,("Start of first in pair '%s'\n", start));
  653.     while ((*end) && !((*end == ' ') || (*end == ')')))
  654.       end++;
  655.     if (!*end) {
  656.       start = end;
  657.       continue;                 /* Always check for the end. */
  658.     }
  659.     DEBUG(5,("End of first in pair '%s'\n", end));
  660.     if ((match_string = mangled_match(s, start, end-start))) {
  661.       DEBUG(5,("Found a match\n"));
  662.       /* Found a match. */
  663.       start = end+1;            /* Point to start of what it is to become. */
  664.       DEBUG(5,("Start of second in pair '%s'\n", start));
  665.       end = start;
  666.       np = new_string;
  667.       while ((*end)             /* Not the end of string. */
  668.              && (*end != ')')   /* Not the end of the pattern. */
  669.              && (*end != '*'))  /* Not a wildcard. */
  670.         *np++ = *end++;
  671.       if (!*end) {
  672.         start = end;
  673.         continue;               /* Always check for the end. */
  674.       }
  675.       if (*end == '*') {
  676.         strcpy(np, match_string);
  677.         np += strlen(match_string);
  678.         end++;                  /* Skip the '*' */
  679.         while ((*end)             /* Not the end of string. */
  680.                && (*end != ')')   /* Not the end of the pattern. */
  681.                && (*end != '*'))  /* Not a wildcard. */
  682.           *np++ = *end++;
  683.       }
  684.       if (!*end) {
  685.         start = end;
  686.         continue;               /* Always check for the end. */
  687.       }
  688.       *np++ = '\0';             /* NULL terminate it. */
  689.       DEBUG(5,("End of second in pair '%s'\n", end));
  690.       strcpy(s, new_string);    /* Substitute with the new name. */
  691.       strupper(s);
  692.       DEBUG(5,("s is now '%s'\n", s));
  693.       return True;              /* DONE! */
  694.     } else {
  695.       start = end;              /* Skip a bit which cannot be wanted */
  696.                                 /* anymore. */
  697.     }
  698.     start++;
  699.   }
  700.   return False;
  701. }
  702.  
  703. /****************************************************************************
  704. do the actual mangling to 8.3 format
  705. ****************************************************************************/
  706. void mangle_name_83(char *s, char *MangledMap)
  707. {
  708.   int csum = str_checksum(s);
  709.   char *p;
  710.   char extension[4] = "";
  711.   char base[9]="";
  712.   int baselen = 0;
  713.   int extlen = 0;
  714.  
  715.   valid_initialise();
  716.  
  717.   if (MangledMap && *MangledMap) {
  718.     if (do_fwd_mangled_map(s, MangledMap))
  719.       return;
  720.   }
  721.  
  722.   p = strrchr(s,'.');  
  723.   if (p)
  724.     {
  725.       BOOL all_lower = ((!strhasupper(p+1)) && (strlen(p+1) < 4));
  726.       if (all_lower)
  727.     {
  728.       *p = 0;
  729.       csum = str_checksum(s);
  730.       *p = '.';
  731.     }
  732.     }
  733.       
  734.  
  735.   strupper(s);
  736.  
  737.   DEBUG(5,("Mangling name %s to ",s));
  738.  
  739.   if (p)
  740.     {
  741.       if (p == s)
  742.     strcpy(extension,"___");
  743.       else
  744.     {
  745.       *p++ = 0;
  746.       while (*p && extlen < 3)
  747.         {
  748.           if (VALID_DOS_PCHAR(p) && *p != '.')
  749.         extension[extlen++] = *p;
  750.           p++;
  751.         }
  752.       extension[extlen] = 0;
  753.     }
  754.     }
  755.  
  756.   p = s;
  757.  
  758.   while (*p && baselen < 5)
  759.     {
  760.       if (VALID_DOS_PCHAR(p) && *p != '.')
  761.     base[baselen++] = *p;
  762.       p++;
  763.     }
  764.   base[baselen] = 0;
  765.  
  766.   csum = csum % (36*36);
  767.  
  768.     sprintf(s,"%s%c%c%c",base,magic_char,base36(csum/36),base36(csum%36));
  769.  
  770.   if (*extension)
  771.     {
  772.       strcat(s,".");
  773.       strcat(s,extension);
  774.     }
  775.   DEBUG(5,("%s\n",s));
  776. }
  777.  
  778.  
  779. /****************************************************************************
  780. convert a filename to 8.3 format. return True if successful.
  781. ****************************************************************************/
  782. BOOL name_convert(char *OutName,char *InName,BOOL mangle, char *MangledMap)
  783. {
  784.   /* initially just copy it */
  785.   strcpy(OutName,InName);
  786.  
  787.   /* check if it's already in 8.3 format */
  788.   if (is_8_3(OutName))
  789.     {
  790.       strupper(OutName);
  791.       return(True);
  792.     }
  793.  
  794.   if (!mangle)
  795.     return(False);
  796.  
  797.   DEBUG(5,("Converted name %s ",OutName));
  798.  
  799.   /* mangle it into 8.3 */
  800.   push_mangled_name(OutName);  
  801.   mangle_name_83(OutName, MangledMap);
  802.  
  803.   DEBUG(5,("to %s\n",OutName));
  804.  
  805.   
  806.   return(True);
  807. }
  808.  
  809.