first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[kamenim/samba-autobuild/.git] / source3 / smbd / mangle.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Name mangling
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /* -------------------------------------------------------------------------- **
23  * Notable problems...
24  *
25  *  March/April 1998  CRH
26  *  - Many of the functions in this module overwrite string buffers passed to
27  *    them.  This causes a variety of problems and is, generally speaking,
28  *    dangerous and scarry.  See the kludge notes in name_map_mangle()
29  *    below.
30  *  - It seems that something is calling name_map_mangle() twice.  The
31  *    first call is probably some sort of test.  Names which contain
32  *    illegal characters are being doubly mangled.  I'm not sure, but
33  *    I'm guessing the problem is in server.c.
34  *
35  * -------------------------------------------------------------------------- **
36  */
37
38 /* -------------------------------------------------------------------------- **
39  * History...
40  *
41  *  March/April 1998  CRH
42  *  Updated a bit.  Rewrote is_mangled() to be a bit more selective.
43  *  Rewrote the mangled name cache.  Added comments here and there.
44  *  &c.
45  * -------------------------------------------------------------------------- **
46  */
47
48 #include "includes.h"
49
50
51 /* -------------------------------------------------------------------------- **
52  * External Variables...
53  */
54
55 extern int DEBUGLEVEL;      /* Global debug level.                            */
56 extern int case_default;    /* Are conforming 8.3 names all upper or lower?   */
57 extern BOOL case_mangle;    /* If true, all chars in 8.3 should be same case. */
58
59 /* -------------------------------------------------------------------------- **
60  * Other stuff...
61  *
62  * magic_char     - This is the magic char used for mangling.  It's
63  *                  global.  There is a call to lp_magicchar() in server.c
64  *                  that is used to override the initial value.
65  *
66  * MANGLE_BASE    - This is the number of characters we use for name mangling.
67  *
68  * basechars      - The set characters used for name mangling.  This
69  *                  is static (scope is this file only).
70  *
71  * mangle()       - Macro used to select a character from basechars (i.e.,
72  *                  mangle(n) will return the nth digit, modulo MANGLE_BASE).
73  *
74  * chartest       - array 0..255.  The index range is the set of all possible
75  *                  values of a byte.  For each byte value, the content is a
76  *                  two nibble pair.  See BASECHAR_MASK and ILLEGAL_MASK,
77  *                  below.
78  *
79  * ct_initialized - False until the chartest array has been initialized via
80  *                  a call to init_chartest().
81  *
82  * BASECHAR_MASK  - Masks the upper nibble of a one-byte value.
83  *
84  * ILLEGAL_MASK   - Masks the lower nibble of a one-byte value.
85  *
86  * isbasecahr()   - Given a character, check the chartest array to see
87  *                  if that character is in the basechars set.  This is
88  *                  faster than using strchr().
89  *
90  * isillegal()    - Given a character, check the chartest array to see
91  *                  if that character is in the illegal characters set.
92  *                  This is faster than using strchr().
93  *
94  * mangled_cache  - Cache header used for storing mangled -> original
95  *                  reverse maps.
96  *
97  * mc_initialized - False until the mangled_cache structure has been
98  *                  initialized via a call to reset_mangled_cache().
99  *
100  * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the
101  *                  cache.  A value of 0 indicates "infinite".
102  *
103  * MANGLED_CACHE_MAX_MEMORY  - Default maximum amount of memory for the
104  *                  cache.  When the cache was kept as an array of 256
105  *                  byte strings, the default cache size was 50 entries.
106  *                  This required a fixed 12.5Kbytes of memory.  The
107  *                  mangled stack parameter is no longer used (though
108  *                  this might change).  We're now using a fixed 16Kbyte
109  *                  maximum cache size.  This will probably be much more
110  *                  than 50 entries.
111  */
112
113 char magic_char = '~';
114
115 static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
116 #define MANGLE_BASE       (sizeof(basechars)/sizeof(char)-1)
117
118 static unsigned char chartest[256]  = { 0 };
119 static BOOL          ct_initialized = False;
120
121 #define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
122 #define BASECHAR_MASK 0xf0
123 #define ILLEGAL_MASK  0x0f
124 #define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK )
125 #define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK )
126
127 static ubi_cacheRoot mangled_cache[1] = { { { 0 }, 0, 0, 0, 0, 0, 0} };
128 static BOOL          mc_initialized   = False;
129 #define MANGLED_CACHE_MAX_ENTRIES 0
130 #define MANGLED_CACHE_MAX_MEMORY  16384
131
132
133 /* -------------------------------------------------------------------------- **
134  * Functions...
135  */
136
137 /* ************************************************************************** **
138  * Initialize the static character test array.
139  *
140  *  Input:  none
141  *
142  *  Output: none
143  *
144  *  Notes:  This function changes (loads) the contents of the <chartest>
145  *          array.  The scope of <chartest> is this file.
146  *
147  * ************************************************************************** **
148  */
149 static void init_chartest( void )
150   {
151   char          *illegalchars = "*\\/?<>|\":";
152   unsigned char *s;
153   
154   memset( (char *)chartest, '\0', 256 );
155
156   for( s = (unsigned char *)illegalchars; *s; s++ )
157     chartest[*s] = ILLEGAL_MASK;
158
159   for( s = (unsigned char *)basechars; *s; s++ )
160     chartest[*s] |= BASECHAR_MASK;
161
162   ct_initialized = True;
163   } /* init_chartest */
164
165 /* ************************************************************************** **
166  * Return True if a name is a special msdos reserved name.
167  *
168  *  Input:  fname - String containing the name to be tested.
169  *
170  *  Output: True, if the name matches one of the list of reserved names.
171  *
172  *  Notes:  This is a static function called by is_8_3(), below.
173  *
174  * ************************************************************************** **
175  */
176 static BOOL is_reserved_msdos( char *fname )
177   {
178   char upperFname[13];
179   char *p;
180
181   StrnCpy (upperFname, fname, 12);
182
183   /* lpt1.txt and con.txt etc are also illegal */
184   p = strchr(upperFname,'.');
185   if( p )
186     *p = '\0';
187
188   strupper( upperFname );
189   p = upperFname + 1;
190   switch( upperFname[0] )
191     {
192     case 'A':
193       if( 0 == strcmp( p, "UX" ) )
194         return( True );
195       break;
196     case 'C':
197       if( (0 == strcmp( p, "LOCK$" ))
198        || (0 == strcmp( p, "ON" ))
199        || (0 == strcmp( p, "OM1" ))
200        || (0 == strcmp( p, "OM2" ))
201        || (0 == strcmp( p, "OM3" ))
202        || (0 == strcmp( p, "OM4" ))
203         )
204         return( True );
205       break;
206     case 'L':
207       if( (0 == strcmp( p, "PT1" ))
208        || (0 == strcmp( p, "PT2" ))
209        || (0 == strcmp( p, "PT3" ))
210         )
211         return( True );
212       break;
213     case 'N':
214       if( 0 == strcmp( p, "UL" ) )
215         return( True );
216       break;
217     case 'P':
218       if( 0 == strcmp( p, "RN" ) )
219         return( True );
220       break;
221     }
222
223   return( False );
224   } /* is_reserved_msdos */
225
226 /* ************************************************************************** **
227  * Determine whether or not a given name contains illegal characters, even
228  * long names.
229  *
230  *  Input:  name  - The name to be tested.
231  *
232  *  Output: True if an illegal character was found in <name>, else False.
233  *
234  *  Notes:  This is used to test a name on the host system, long or short,
235  *          for characters that would be illegal on most client systems,
236  *          particularly DOS and Windows systems.  Unix and AmigaOS, for
237  *          example, allow a filenames which contain such oddities as
238  *          quotes (").  If a name is found which does contain an illegal
239  *          character, it is mangled even if it conforms to the 8.3
240  *          format.
241  *
242  * ************************************************************************** **
243  */
244 static BOOL is_illegal_name( char *name )
245   {
246   unsigned char *s;
247   int            skip;
248
249   if( !name )
250     return( True );
251
252   if( !ct_initialized )
253     init_chartest();
254
255   s = (unsigned char *)name;
256   while( *s )
257     {
258     skip = skip_multibyte_char( *s );
259     if( skip != 0 )
260       {
261       s += skip;
262       }
263     else
264       {
265       if( isillegal( *s ) )
266         return( True );
267       else
268         s++;
269       }
270     }
271
272   return( False );
273   } /* is_illegal_name */
274
275 /* ************************************************************************** **
276  * Return True if the name *could be* a mangled name.
277  *
278  *  Input:  s - A path name - in UNIX pathname format.
279  *
280  *  Output: True if the name matches the pattern described below in the
281  *          notes, else False.
282  *
283  *  Notes:  The input name is *not* tested for 8.3 compliance.  This must be
284  *          done separately.  This function returns true if the name contains
285  *          a magic character followed by excactly two characters from the
286  *          basechars list (above), which in turn are followed either by the
287  *          nul (end of string) byte or a dot (extension) or by a '/' (end of
288  *          a directory name).
289  *
290  * ************************************************************************** **
291  */
292 BOOL is_mangled( char *s )
293   {
294   char *magic;
295
296   if( !ct_initialized )
297     init_chartest();
298
299   magic = strchr( s, magic_char );
300   while( magic && magic[1] && magic[2] )          /* 3 chars, 1st is magic. */
301     {
302     if( ('.' == magic[3] || '/' == magic[3] || !(magic[3]))          /* Ends with '.' or nul or '/' ?  */
303      && isbasechar( toupper(magic[1]) )           /* is 2nd char basechar?  */
304      && isbasechar( toupper(magic[2]) ) )         /* is 3rd char basechar?  */
305       return( True );                           /* If all above, then true, */
306     magic = strchr( magic+1, magic_char );      /*    else seek next magic. */
307     }
308   return( False );
309   } /* is_mangled */
310
311 /* ************************************************************************** **
312  * Return True if the name is a valid DOS name in 8.3 DOS format.
313  *
314  *  Input:  fname       - File name to be checked.
315  *          check_case  - If True, and if case_mangle is True, then the
316  *                        name will be checked to see if all characters
317  *                        are the correct case.  See case_mangle and
318  *                        case_default above.
319  *
320  *  Output: True if the name is a valid DOS name, else FALSE.
321  *
322  * ************************************************************************** **
323  */
324 BOOL is_8_3( char *fname, BOOL check_case )
325   {
326   int   len;
327   int   l;
328   int   skip;
329   char *p;
330   char *dot_pos;
331   char *slash_pos = strrchr( fname, '/' );
332
333   /* If there is a directory path, skip it. */
334   if( slash_pos )
335     fname = slash_pos + 1;
336   len = strlen( fname );
337
338   DEBUG( 5, ( "Checking %s for 8.3\n", fname ) );
339
340   /* Can't be 0 chars or longer than 12 chars */
341   if( (len == 0) || (len > 12) )
342     return( False );
343
344   /* Mustn't be an MS-DOS Special file such as lpt1 or even lpt1.txt */
345   if( is_reserved_msdos( fname ) )
346     return( False );
347
348   /* Check that all characters are the correct case, if asked to do so. */
349   if( check_case && case_mangle )
350     {
351     switch( case_default )
352       {
353       case CASE_LOWER:
354         if( strhasupper( fname ) )
355           return(False);
356         break;
357       case CASE_UPPER:
358         if( strhaslower( fname ) )
359           return(False);
360         break;
361       }
362     }
363
364   /* Can't contain invalid dos chars */
365   /* Windows use the ANSI charset.
366      But filenames are translated in the PC charset.
367      This Translation may be more or less relaxed depending
368      the Windows application. */
369
370   /* %%% A nice improvment to name mangling would be to translate
371      filename to ANSI charset on the smb server host */
372
373   p       = fname;
374   dot_pos = NULL;
375   while( *p )
376     {
377     if( (skip = skip_multibyte_char( *p )) != 0 )
378       p += skip;
379     else 
380       {
381       if( *p == '.' && !dot_pos )
382         dot_pos = (char *)p;
383       else
384         if( !isdoschar( *p ) )
385           return( False );
386       p++;
387       }
388     }
389
390   /* no dot and less than 9 means OK */
391   if( !dot_pos )
392     return( len <= 8 );
393         
394   l = PTR_DIFF( dot_pos, fname );
395
396   /* base must be at least 1 char except special cases . and .. */
397   if( l == 0 )
398     return( 0 == strcmp( fname, "." ) || 0 == strcmp( fname, ".." ) );
399
400   /* base can't be greater than 8 */
401   if( l > 8 )
402     return( False );
403
404   /* see smb.conf(5) for a description of the 'strip dot' parameter. */
405   if( lp_strip_dot()
406    && len - l == 1
407    && !strchr( dot_pos + 1, '.' ) )
408     {
409     *dot_pos = 0;
410     return( True );
411     }
412
413   /* extension must be between 1 and 3 */
414   if( (len - l < 2 ) || (len - l > 4) )
415     return( False );
416
417   /* extensions may not have a dot */
418   if( strchr( dot_pos+1, '.' ) )
419     return( False );
420
421   /* must be in 8.3 format */
422   return( True );
423   } /* is_8_3 */
424
425
426 /* ************************************************************************** **
427  * Compare two cache keys and return a value indicating their ordinal
428  * relationship.
429  *
430  *  Input:  ItemPtr - Pointer to a comparison key.  In this case, this will
431  *                    be a mangled name string.
432  *          NodePtr - Pointer to a node in the cache.  The node structure
433  *                    will be followed in memory by a mangled name string.
434  *
435  *  Output: A signed integer, as follows:
436  *            (x < 0)  <==> Key1 less than Key2
437  *            (x == 0) <==> Key1 equals Key2
438  *            (x > 0)  <==> Key1 greater than Key2
439  *
440  *  Notes:  This is a ubiqx-style comparison routine.  See ubi_BinTree for
441  *          more info.
442  *
443  * ************************************************************************** **
444  */
445 static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
446   {
447   char *Key1 = (char *)ItemPtr;
448   char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
449
450   return( StrCaseCmp( Key1, Key2 ) );
451   } /* cache_compare */
452
453 /* ************************************************************************** **
454  * Free a cache entry.
455  *
456  *  Input:  WarrenZevon - Pointer to the entry that is to be returned to
457  *                        Nirvana.
458  *  Output: none.
459  *
460  *  Notes:  This function gets around the possibility that the standard
461  *          free() function may be implemented as a macro, or other evil
462  *          subversions (oh, so much fun).
463  *
464  * ************************************************************************** **
465  */
466 static void cache_free_entry( ubi_trNodePtr WarrenZevon )
467   {
468   free( WarrenZevon );
469   } /* cache_free_entry */
470
471 /* ************************************************************************** **
472  * Initializes or clears the mangled cache.
473  *
474  *  Input:  none.
475  *  Output: none.
476  *
477  *  Notes:  There is a section below that is commented out.  It shows how
478  *          one might use lp_ calls to set the maximum memory and entry size
479  *          of the cache.  You might also want to remove the constants used
480  *          in ubi_cacheInit() and replace them with lp_ calls.  If so, then
481  *          the calls to ubi_cacheSetMax*() would be moved into the else
482  *          clause.  Another option would be to pass in the max_entries and
483  *          max_memory values as parameters.  crh 09-Apr-1998.
484  *
485  * ************************************************************************** **
486  */
487 void reset_mangled_cache( void )
488   {
489   if( !mc_initialized )
490     {
491     (void)ubi_cacheInit( mangled_cache,
492                          cache_compare,
493                          cache_free_entry,
494                          MANGLED_CACHE_MAX_ENTRIES,
495                          MANGLED_CACHE_MAX_MEMORY );
496     mc_initialized = True;
497     }
498   else
499     {
500     (void)ubi_cacheClear( mangled_cache );
501     }
502
503   /*
504   (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
505   (void)ubi_cacheSetMaxMemory(  mangled_cache, lp_mangled_cache_memory() );
506   */
507   } /* reset_mangled_cache  */
508
509
510 /* ************************************************************************** **
511  * Add a mangled name into the cache.
512  *
513  *  Notes:  If the mangled cache has not been initialized, then the
514  *          function will simply fail.  It could initialize the cache,
515  *          but that's not the way it was done before I changed the
516  *          cache mechanism, so I'm sticking with the old method.
517  *
518  *          If the extension of the raw name maps directly to the
519  *          extension of the mangled name, then we'll store both names
520  *          *without* extensions.  That way, we can provide consistent
521  *          reverse mangling for all names that match.  The test here is
522  *          a bit more careful than the one done in earlier versions of
523  *          mangle.c:
524  *
525  *            - the extension must exist on the raw name,
526  *            - it must be all lower case
527  *            - it must match the mangled extension (to prove that no
528  *              mangling occurred).
529  *
530  *  crh 07-Apr-1998
531  *
532  * ************************************************************************** **
533  */
534 static void cache_mangled_name( char *mangled_name, char *raw_name )
535   {
536   ubi_cacheEntryPtr new_entry;
537   char             *s1;
538   char             *s2;
539   size_t               mangled_len;
540   size_t               raw_len;
541   size_t               i;
542
543   /* If the cache isn't initialized, give up. */
544   if( !mc_initialized )
545     return;
546
547   /* Init the string lengths. */
548   mangled_len = strlen( mangled_name );
549   raw_len     = strlen( raw_name );
550
551   /* See if the extensions are unmangled.  If so, store the entry
552    * without the extension, thus creating a "group" reverse map.
553    */
554   s1 = strrchr( mangled_name, '.' );
555   if( s1 && (s2 = strrchr( raw_name, '.' )) )
556     {
557     i = 1;
558     while( s1[i] && (tolower( s1[1] ) == s2[i]) )
559       i++;
560     if( !s1[i] && !s2[i] )
561       {
562       mangled_len -= i;
563       raw_len     -= i;
564       }
565     }
566
567   /* Allocate a new cache entry.  If the allocation fails, just return. */
568   i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
569   new_entry = malloc( i );
570   if( !new_entry )
571     return;
572
573   /* Fill the new cache entry, and add it to the cache. */
574   s1 = (char *)(new_entry + 1);
575   s2 = (char *)&(s1[mangled_len + 1]);
576   (void)StrnCpy( s1, mangled_name, mangled_len );
577   (void)StrnCpy( s2, raw_name,     raw_len );
578   ubi_cachePut( mangled_cache, i, new_entry, s1 );
579   } /* cache_mangled_name */
580
581 /* ************************************************************************** **
582  * Check for a name on the mangled name stack
583  *
584  *  Input:  s - Input *and* output string buffer.
585  *
586  *  Output: True if the name was found in the cache, else False.
587  *
588  *  Notes:  If a reverse map is found, the function will overwrite the string
589  *          space indicated by the input pointer <s>.  This is frightening.
590  *          It should be rewritten to return NULL if the long name was not
591  *          found, and a pointer to the long name if it was found.
592  *
593  * ************************************************************************** **
594  */
595
596 BOOL check_mangled_cache( char *s )
597 {
598   ubi_cacheEntryPtr FoundPtr;
599   char             *ext_start = NULL;
600   char             *found_name;
601   char             *saved_ext = NULL;
602
603   /* If the cache isn't initialized, give up. */
604   if( !mc_initialized )
605     return( False );
606
607   FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
608
609   /* If we didn't find the name *with* the extension, try without. */
610   if( !FoundPtr )
611   {
612     ext_start = strrchr( s, '.' );
613     if( ext_start )
614     {
615       if((saved_ext = strdup(ext_start)) == NULL)
616         return False;
617
618       *ext_start = '\0';
619       FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
620       /* 
621        * At this point s is the name without the
622        * extension. We re-add the extension if saved_ext
623        * is not null, before freeing saved_ext.
624        */
625     }
626   }
627
628   /* Okay, if we haven't found it we're done. */
629   if( !FoundPtr )
630   {
631     if(saved_ext)
632     {
633       /* Replace the saved_ext as it was truncated. */
634       (void)pstrcat( s, saved_ext );
635       free(saved_ext);
636     }
637     return( False );
638   }
639
640   /* If we *did* find it, we need to copy it into the string buffer. */
641   found_name = (char *)(FoundPtr + 1);
642   found_name += (strlen( found_name ) + 1);
643
644   DEBUG( 3, ("Found %s on mangled stack ", s) );
645
646   (void)pstrcpy( s, found_name );
647   if( saved_ext )
648   {
649     /* Replace the saved_ext as it was truncated. */
650     (void)pstrcat( s, saved_ext );
651     free(saved_ext);
652   }
653
654   DEBUG( 3, ("as %s\n", s) );
655
656   return( True );
657 } /* check_mangled_cache */
658
659
660 /* ************************************************************************** **
661  * Used only in do_fwd_mangled_map(), below.
662  * ************************************************************************** **
663  */
664 static char *map_filename( char *s,         /* This is null terminated */
665                            char *pattern,   /* This isn't. */
666                            int len )        /* This is the length of pattern. */
667   {
668   static pstring matching_bit;  /* The bit of the string which matches */
669                                 /* a * in pattern if indeed there is a * */
670   char *sp;                     /* Pointer into s. */
671   char *pp;                     /* Pointer into p. */
672   char *match_start;            /* Where the matching bit starts. */
673   pstring pat;
674
675   StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */
676   pstrcpy( matching_bit, "" );  /* Match but no star gets this. */
677   pp = pat;                     /* Initialize the pointers. */
678   sp = s;
679
680   if( strequal(s, ".") || strequal(s, ".."))
681     {
682     return NULL;                /* Do not map '.' and '..' */
683     }
684
685   if( (len == 1) && (*pattern == '*') )
686     {
687     return NULL;                /* Impossible, too ambiguous for */
688     }                           /* words! */
689
690   while( (*sp)                  /* Not the end of the string. */
691       && (*pp)                  /* Not the end of the pattern. */
692       && (*sp == *pp)           /* The two match. */
693       && (*pp != '*') )         /* No wildcard. */
694     {
695     sp++;                       /* Keep looking. */
696     pp++;
697     }
698
699   if( !*sp && !*pp )            /* End of pattern. */
700     return( matching_bit );     /* Simple match.  Return empty string. */
701
702   if( *pp == '*' )
703     {
704     pp++;                       /* Always interrested in the chacter */
705                                 /* after the '*' */
706     if( !*pp )                  /* It is at the end of the pattern. */
707       {
708       StrnCpy( matching_bit, s, sp-s );
709       return( matching_bit );
710       }
711     else
712       {
713       /* The next character in pattern must match a character further */
714       /* along s than sp so look for that character. */
715       match_start = sp;
716       while( (*sp)              /* Not the end of s. */
717           && (*sp != *pp) )     /* Not the same  */
718         sp++;                   /* Keep looking. */
719       if( !*sp )                /* Got to the end without a match. */
720         {
721         return( NULL );
722         }                       /* Still hope for a match. */
723       else
724         {
725         /* Now sp should point to a matching character. */
726         StrnCpy(matching_bit, match_start, sp-match_start);
727         /* Back to needing a stright match again. */
728         while( (*sp)            /* Not the end of the string. */
729             && (*pp)            /* Not the end of the pattern. */
730             && (*sp == *pp) )   /* The two match. */
731           {
732           sp++;                 /* Keep looking. */
733           pp++;
734           }
735         if( !*sp && !*pp )      /* Both at end so it matched */
736           return( matching_bit );
737         else
738           return( NULL );
739         }
740       }
741     }
742   return( NULL );               /* No match. */
743   } /* map_filename */
744
745
746 /* ************************************************************************** **
747  * MangledMap is a series of name pairs in () separated by spaces.
748  * If s matches the first of the pair then the name given is the
749  * second of the pair.  A * means any number of any character and if
750  * present in the second of the pair as well as the first the
751  * matching part of the first string takes the place of the * in the
752  * second.
753  *
754  * I wanted this so that we could have RCS files which can be used
755  * by UNIX and DOS programs.  My mapping string is (RCS rcs) which
756  * converts the UNIX RCS file subdirectory to lowercase thus
757  * preventing mangling.
758  *
759  * (I think Andrew wrote the above, but I'm not sure. -- CRH)
760  *
761  * See 'mangled map' in smb.conf(5).
762  *
763  * ************************************************************************** **
764  */
765 static void do_fwd_mangled_map(char *s, char *MangledMap)
766   {
767   char *start=MangledMap;       /* Use this to search for mappings. */
768   char *end;                    /* Used to find the end of strings. */
769   char *match_string;
770   pstring new_string;           /* Make up the result here. */
771   char *np;                     /* Points into new_string. */
772
773   DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) );
774   while( *start )
775     {
776     while( (*start) && (*start != '(') )
777       start++;
778     if( !*start )
779       continue;                 /* Always check for the end. */
780     start++;                    /* Skip the ( */
781     end = start;                /* Search for the ' ' or a ')' */
782     DEBUG( 5, ("Start of first in pair '%s'\n", start) );
783     while( (*end) && !((*end == ' ') || (*end == ')')) )
784       end++;
785     if( !*end )
786       {
787       start = end;
788       continue;                 /* Always check for the end. */
789       }
790     DEBUG( 5, ("End of first in pair '%s'\n", end) );
791     if( (match_string = map_filename( s, start, end-start )) )
792       {
793       DEBUG( 5, ("Found a match\n") );
794       /* Found a match. */
795       start = end + 1;          /* Point to start of what it is to become. */
796       DEBUG( 5, ("Start of second in pair '%s'\n", start) );
797       end = start;
798       np = new_string;
799       while( (*end)             /* Not the end of string. */
800           && (*end != ')')      /* Not the end of the pattern. */
801           && (*end != '*') )    /* Not a wildcard. */
802         *np++ = *end++;
803       if( !*end )
804         {
805         start = end;
806         continue;               /* Always check for the end. */
807         }
808       if( *end == '*' )
809         {
810         pstrcpy( np, match_string );
811         np += strlen( match_string );
812         end++;                  /* Skip the '*' */
813         while( (*end)             /* Not the end of string. */
814             && (*end != ')')      /* Not the end of the pattern. */
815             && (*end != '*') )    /* Not a wildcard. */
816           *np++ = *end++;
817         }
818       if( !*end )
819         {
820         start = end;
821         continue;               /* Always check for the end. */
822         }
823       *np++ = '\0';             /* NULL terminate it. */
824       DEBUG(5,("End of second in pair '%s'\n", end));
825       pstrcpy( s, new_string );  /* Substitute with the new name. */
826       DEBUG( 5, ("s is now '%s'\n", s) );
827       }
828     start = end;              /* Skip a bit which cannot be wanted anymore. */
829     start++;
830     }
831   } /* do_fwd_mangled_map */
832
833 /*****************************************************************************
834  * do the actual mangling to 8.3 format
835  * the buffer must be able to hold 13 characters (including the null)
836  *****************************************************************************
837  */
838 void mangle_name_83( char *s)
839   {
840   int csum;
841   char *p;
842   char extension[4];
843   char base[9];
844   int baselen = 0;
845   int extlen = 0;
846   int skip;
847
848   extension[0] = 0;
849   base[0] = 0;
850
851   p = strrchr(s,'.');  
852   if( p && (strlen(p+1) < (size_t)4) )
853     {
854     BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */
855
856     if( all_normal && p[1] != 0 )
857       {
858       *p = 0;
859       csum = str_checksum( s );
860       *p = '.';
861       }
862     else
863       csum = str_checksum(s);
864     }
865   else
866     csum = str_checksum(s);
867
868   strupper( s );
869
870   DEBUG( 5, ("Mangling name %s to ",s) );
871
872   if( p )
873     {
874     if( p == s )
875       safe_strcpy( extension, "___", 3 );
876     else
877       {
878       *p++ = 0;
879       while( *p && extlen < 3 )
880         {
881         skip = skip_multibyte_char( *p );
882         switch( skip )
883           {
884           case 2: 
885             if( extlen < 2 )
886               {
887               extension[extlen++] = p[0];
888               extension[extlen++] = p[1];
889               }
890             else 
891               {
892               extension[extlen++] = mangle( (unsigned char)*p );
893               }
894             p += 2;
895             break;
896           case 1:
897             extension[extlen++] = p[0];
898             p++;
899             break;
900           default:
901             if( isdoschar (*p) && *p != '.' )
902               extension[extlen++] = p[0];
903             p++;
904             break;
905           }
906         }
907       extension[extlen] = 0;
908       }
909     }
910
911   p = s;
912
913   while( *p && baselen < 5 )
914     {
915     skip = skip_multibyte_char(*p);
916     switch( skip )
917       {
918       case 2:
919         if( baselen < 4 )
920           {
921           base[baselen++] = p[0];
922           base[baselen++] = p[1];
923           }
924         else 
925           {
926           base[baselen++] = mangle( (unsigned char)*p );
927           }
928         p += 2;
929         break;
930       case 1:
931         base[baselen++] = p[0];
932         p++;
933         break;
934       default:
935         if( isdoschar( *p ) && *p != '.' )
936           base[baselen++] = p[0];
937         p++;
938         break;
939       }
940     }
941   base[baselen] = 0;
942
943   csum = csum % (MANGLE_BASE*MANGLE_BASE);
944
945   (void)slprintf(s, 12, "%s%c%c%c",
946                  base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
947
948   if( *extension )
949     {
950     (void)pstrcat( s, "." );
951     (void)pstrcat( s, extension );
952     }
953
954   DEBUG( 5, ( "%s\n", s ) );
955
956   } /* mangle_name_83 */
957
958 /*****************************************************************************
959  * Convert a filename to DOS format.  Return True if successful.
960  *
961  *  Input:  OutName - Source *and* destination buffer. 
962  *
963  *                    NOTE that OutName must point to a memory space that
964  *                    is at least 13 bytes in size!
965  *
966  *          need83  - If False, name mangling will be skipped unless the
967  *                    name contains illegal characters.  Mapping will still
968  *                    be done, if appropriate.  This is probably used to
969  *                    signal that a client does not require name mangling,
970  *                    thus skipping the name mangling even on shares which
971  *                    have name-mangling turned on.
972  *          cache83 - If False, the mangled name cache will not be updated.
973  *                    This is usually used to prevent that we overwrite
974  *                    a conflicting cache entry prematurely, i.e. before
975  *                    we know whether the client is really interested in the
976  *                    current name.  (See PR#13758).  UKD.
977  *          snum    - Share number.  This identifies the share in which the
978  *                    name exists.
979  *
980  *  Output: Returns False only if the name wanted mangling but the share does
981  *          not have name mangling turned on.
982  *
983  * ****************************************************************************
984  */
985 BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)
986 {
987         char *map;
988         DEBUG(5,("name_map_mangle( %s, need83 = %s, cache83 = %s, %d )\n", OutName,
989                 need83 ? "TRUE" : "FALSE", cache83 ? "TRUE" : "FALSE", snum));
990
991 #ifdef MANGLE_LONG_FILENAMES
992         if( !need83 && is_illegal_name(OutName) )
993                 need83 = True;
994 #endif  
995
996         /* apply any name mappings */
997         map = lp_mangled_map(snum);
998
999         if (map && *map) {
1000                 do_fwd_mangled_map( OutName, map );
1001         }
1002
1003         /* check if it's already in 8.3 format */
1004         if (need83 && !is_8_3(OutName, True)) {
1005                 char *tmp = NULL; 
1006
1007                 if (!lp_manglednames(snum)) {
1008                         return(False);
1009                 }
1010
1011                 /* mangle it into 8.3 */
1012                 if (cache83)
1013                         tmp = strdup(OutName);
1014
1015                 mangle_name_83(OutName);
1016
1017                 if(tmp != NULL) {
1018                         cache_mangled_name(OutName, tmp);
1019                         free(tmp);
1020                 }
1021         }
1022
1023         DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName));
1024         return(True);
1025 } /* name_map_mangle */
1026