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