removed unused function
[kai/samba.git] / source3 / smbd / mangle.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    Name mangling with persistent tdb
5    Copyright (C) Simo Sorce 2001
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   Rewritten from scrach in 2001 by Simo Sorce <idra@samba.org>
24  ****************************************************************************/
25
26 #include "includes.h"
27
28
29 /* -------------------------------------------------------------------------- **
30  * External Variables...
31  */
32
33 extern int case_default;    /* Are conforming 8.3 names all upper or lower?   */
34 extern BOOL case_mangle;    /* If true, all chars in 8.3 should be same case. */
35
36 char magic_char = '~';
37
38 /* -------------------------------------------------------------------- */
39
40 #define MANGLE_TDB_VERSION              "20010927"
41 #define MANGLE_TDB_FILE_NAME            "mangle.tdb"
42 #define MANGLED_PREFIX                  "MANGLED_"
43 #define LONG_PREFIX                     "LONG_"
44 #define COUNTER_PREFIX                  "COUNTER_"
45 #define MANGLE_COUNTER_MAX              99
46 #define MANGLE_SUFFIX_SIZE              3 /* "~XX" */
47
48
49 static TDB_CONTEXT      *mangle_tdb;
50
51 BOOL init_mangle_tdb(void)
52 {
53         char *tdbfile;
54         
55         tdbfile = lock_path(MANGLE_TDB_FILE_NAME); /* this return a static pstring do not try to free it */
56
57         /* Open tdb */
58         if (!(mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600)))
59         {
60                 DEBUG(0, ("Unable to open Mangle TDB\n"));
61                 return False;
62         }
63
64         return True;
65 }
66
67 /* trasform a unicode string into a dos charset string */
68 static int ucs2_to_dos(char *dest, const smb_ucs2_t *src, int dest_len)
69 {
70         int src_len, ret;
71
72         if (dest_len == -1) {
73                 dest_len = sizeof(pstring);
74         }
75
76         src_len = strlen_w(src)* sizeof(smb_ucs2_t);
77         
78         ret = convert_string(CH_UCS2, CH_DOS, src, src_len, dest, dest_len);
79         if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
80
81         return ret;
82 }
83
84 /* trasform in a string that contain only valid chars for win filenames */
85 static void strvalid(smb_ucs2_t *src)
86 {
87         if (!src || !*src) return;
88
89         while (*src) {
90                 if (!isvalid83_w(*src)) *src = UCS2_CHAR('_');
91                 src++;
92         }
93 }
94
95
96 /* return False if something fail and
97  * return 2 alloced unicode strings that contain prefix and extension
98  */
99 static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix, smb_ucs2_t **extension)
100 {
101         size_t ext_len;
102         smb_ucs2_t *p;
103
104         *extension = 0;
105         *prefix = strdup_w(ucs2_string);
106         if (!*prefix)
107         {
108                 DEBUG(0,("mangle_get_prefix: out of memory!\n"));
109                 return NT_STATUS_NO_MEMORY;
110         }
111         if ((p = strrchr_w(*prefix, UCS2_CHAR('.'))))
112         {
113                 p++;
114                 ext_len = strlen_w(p);
115                 if ((ext_len > 0) && (ext_len < 4)
116                         && (NT_STATUS_IS_OK(has_valid_chars(p)))) /* check extension */
117                 {
118                         *(p - 1) = 0;
119                         *extension = strdup_w(p);
120                         if (!*extension)
121                         {
122                                 DEBUG(0,("mangle_get_prefix: out of memory!\n"));
123                                 SAFE_FREE(*prefix);
124                                 return NT_STATUS_NO_MEMORY;
125                         }
126                 }
127         }
128         return NT_STATUS_OK;
129 }
130
131
132 /* mangled must contain only the file name, not a path.
133    and MUST be ZERO terminated */
134 smb_ucs2_t *unmangle(const smb_ucs2_t *mangled)
135 {
136         TDB_DATA data, key;
137         fstring keystr;
138         fstring mufname;
139         smb_ucs2_t *pref, *ext, *retstr;
140         size_t long_len, ext_len, muf_len;
141
142         if (strlen_w(mangled) > 12) return NULL;
143         if (!strchr_w(mangled, UCS2_CHAR('~'))) return NULL;
144
145         /* if it is a path refuse to proceed */
146         if (strchr_w(mangled, UCS2_CHAR('/'))) {
147                 DEBUG(10, ("unmangle: cannot unmangle a path\n"));
148                 return NULL;
149         }
150
151         if (NT_STATUS_IS_ERR(mangle_get_prefix(mangled, &pref, &ext)))
152                 return NULL;
153
154         /* mangled names are stored lowercase only */   
155         strlower_w(pref);
156         /* set search key */
157         muf_len = ucs2_to_dos(mufname, pref, sizeof(mufname));
158         SAFE_FREE(pref);
159         if (!muf_len) return NULL;
160         
161         slprintf(keystr, sizeof(keystr) - 1, "%s%s", MANGLED_PREFIX, mufname);
162         key.dptr = keystr;
163         key.dsize = strlen (keystr) + 1;
164         
165         /* get the record */
166         data = tdb_fetch(mangle_tdb, key);
167         
168         if (!data.dptr) /* not found */
169         {
170                 DEBUG(5,("unmangle: failed retrieve from db %s\n", tdb_errorstr(mangle_tdb)));
171                 retstr = NULL;
172                 goto done;
173         }
174
175         if (ext)
176         {
177                 long_len = (data.dsize / 2) - 1;
178                 ext_len = strlen_w(ext);
179                 retstr = (smb_ucs2_t *)malloc((long_len + ext_len + 2)*sizeof(smb_ucs2_t));
180                 if (!retstr)
181                 {
182                         DEBUG(0, ("unamngle: out of memory!\n"));
183                         goto done;
184                 }
185                 strncpy_w(retstr, (smb_ucs2_t *)data.dptr, long_len);
186                 retstr[long_len] = UCS2_CHAR('.');
187                 retstr[long_len + 1] = 0;
188                 strncat_w(retstr, ext, ext_len);
189         }
190         else
191         {
192                 retstr = strdup_w((smb_ucs2_t *)data.dptr);
193                 if (!retstr)
194                 {
195                         DEBUG(0, ("unamngle: out of memory!\n"));
196                         goto done;
197                 }
198
199         }
200
201 done:
202         SAFE_FREE(data.dptr);
203         SAFE_FREE(pref);
204         SAFE_FREE(ext);
205
206         return retstr;
207 }
208
209 /* unmangled must contain only the file name, not a path.
210    and MUST be ZERO terminated.
211    return a new allocated string if the name is yet valid 8.3
212    or is mangled successfully.
213    return null on error.
214  */
215
216 smb_ucs2_t *mangle(const smb_ucs2_t *unmangled)
217 {
218         TDB_DATA data, key, klock;
219         pstring keystr;
220         pstring longname;
221         fstring keylock;
222         fstring mufname;
223         fstring prefix;
224         BOOL tclock = False;
225         char suffix[7];
226         smb_ucs2_t *mangled = NULL;
227         smb_ucs2_t *umpref, *ext, *p = NULL;
228         size_t pref_len, ext_len, ud83_len;
229
230         /* if it is a path refuse to proceed */
231         if (strchr_w(unmangled, UCS2_CHAR('/'))) {
232                 DEBUG(10, ("mangle: cannot mangle a path\n"));
233                 return NULL;
234         }
235
236         /* if it is a valid 8_3 do not mangle again */
237         if (NT_STATUS_IS_OK(is_8_3_w(unmangled)))
238                 return NULL;
239
240         if (NT_STATUS_IS_ERR(mangle_get_prefix(unmangled, &umpref, &ext)))
241                 return NULL;
242
243         /* test if the same is yet mangled */
244
245         /* set search key */
246         pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE);
247         slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
248         key.dptr = keystr;
249         key.dsize = strlen(keystr) + 1;
250
251         /* get the record */
252         data = tdb_fetch (mangle_tdb, key);
253         if (!data.dptr) /* not found */
254         {
255                 smb_ucs2_t temp[9];
256                 size_t c, pos;
257
258                 if (tdb_error(mangle_tdb) != TDB_ERR_NOEXIST)
259                 {
260                         DEBUG(0, ("mangle: database retrieval error: %s\n",
261                                         tdb_errorstr(mangle_tdb)));
262                         goto done;
263                 }
264
265                 /* if not find the first free possibile mangled name */
266
267                 pos = strlen_w(umpref);
268                 if ((8 - MANGLE_SUFFIX_SIZE) < pos)
269                         pos = 8 - MANGLE_SUFFIX_SIZE;
270                 pos++;
271                 do
272                 {
273                         pos--;
274                         if (pos == 0)
275                         {
276                                 DEBUG(0, ("mangle: unable to mangle file name!\n"));
277                                 goto done;
278                         }
279                         strncpy_w(temp, umpref, pos);
280                         temp[pos] = 0;
281                         strlower_w(temp);
282
283                         /* convert any invalid char into '_' */
284                         strvalid(temp);
285                         ud83_len = ucs2_to_dos(prefix, temp, sizeof(prefix));
286                         if (!ud83_len) goto done;
287                 }
288                 while (ud83_len > 8 - MANGLE_SUFFIX_SIZE);
289
290                 slprintf(keylock, sizeof(keylock)-1, "%s%s", COUNTER_PREFIX, prefix);
291                 klock.dptr = keylock;
292                 klock.dsize = strlen(keylock) + 1;
293
294                 c = 0;
295                 data.dptr = (char *)&c;
296                 data.dsize = sizeof(uint32);
297                 /* try to insert a new counter prefix, if it exist the call will
298                    fail (correct) otherwise it will create a new entry with counter set
299                    to 0
300                  */
301                 if(tdb_store(mangle_tdb, klock, data, TDB_INSERT) != TDB_SUCCESS)
302                 {
303                         if (tdb_error(mangle_tdb) != TDB_ERR_EXISTS)
304                         {
305                                 DEBUG(0, ("mangle: database store error: %s\n",
306                                         tdb_errorstr(mangle_tdb)));
307                                 goto done;
308                         }
309                 }
310
311                 /* lock the mangle counter for this prefix */           
312                 if (tdb_chainlock(mangle_tdb, klock))
313                 {
314                         DEBUG(0,("mangle: failed to lock database\n!"));
315                         goto done;
316                 }
317                 tclock = True;
318
319                 data = tdb_fetch(mangle_tdb, klock);
320                 if (!data.dptr)
321                 {
322                         DEBUG(0, ("mangle: database retrieval error: %s\n",
323                                         tdb_errorstr(mangle_tdb)));
324                         goto done;
325                 }
326                 c = *((uint32 *)data.dptr);
327                 c++;
328                 
329                 if (c > MANGLE_COUNTER_MAX)
330                 {
331                         DEBUG(0, ("mangle: error, counter overflow!\n"));
332                         goto done;
333                 }
334                         
335                 temp[pos] = UCS2_CHAR('~');
336                 temp[pos+1] = 0;
337                 snprintf(suffix, 7, "%.6d", c);
338                 strncat_wa(temp, &suffix[7 - MANGLE_SUFFIX_SIZE], MANGLE_SUFFIX_SIZE);
339
340                 ud83_len = ucs2_to_dos(mufname, temp, sizeof(mufname));
341                 if (!ud83_len) goto done;
342                 if (ud83_len > 8)
343                 {
344                         DEBUG(0, ("mangle: darn, logic error aborting!\n"));
345                         goto done;
346                 }
347                         
348                 /* store the long entry with mangled key */
349                 slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
350                 key.dptr = keystr;
351                 key.dsize = strlen (keystr) + 1;
352                 data.dsize = (strlen_w(umpref) + 1) * sizeof (smb_ucs2_t);
353                 data.dptr = (void *)umpref;
354
355                 if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
356                 {
357                         DEBUG(0, ("mangle: database store error: %s\n",
358                                         tdb_errorstr(mangle_tdb)));
359                         goto done;
360                 }
361
362                 /* store the mangled entry with long key*/
363                 pull_ucs2(NULL, longname, umpref, sizeof(longname), 0, STR_TERMINATE);
364                 slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
365                 key.dptr = keystr;
366                 key.dsize = strlen (keystr) + 1;
367                 data.dsize = strlen(mufname) + 1;
368                 data.dptr = mufname;
369                 if (tdb_store(mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
370                 {
371                         DEBUG(0, ("mangle: database store failed: %s\n",
372                                         tdb_errorstr(mangle_tdb)));
373
374                         /* try to delete the mangled key entry to avoid later inconsistency */
375                         slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
376                         key.dptr = keystr;
377                         key.dsize = strlen (keystr) + 1;
378                         if (!tdb_delete(mangle_tdb, key))
379                         {
380                                 DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
381                         }
382                         goto done;
383                 }
384
385                 p = strdup_w(temp);
386                 if (!p)
387                 {
388                         DEBUG(0,("mangle: out of memory!\n"));
389                         goto done;
390                 }
391                 
392                 data.dptr = (char *)&c;
393                 data.dsize = sizeof(uint32);
394                 /* store the counter */
395                 if(tdb_store(mangle_tdb, klock, data, TDB_REPLACE) != TDB_SUCCESS)
396                 {
397                         DEBUG(0, ("mangle: database store failed: %s\n",
398                                         tdb_errorstr(mangle_tdb)));
399                         /* try to delete the mangled and long key entry to avoid later inconsistency */
400                         slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
401                         key.dptr = keystr;
402                         key.dsize = strlen (keystr) + 1;
403                         if (!tdb_delete(mangle_tdb, key))
404                         {
405                                 DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
406                         }
407                         slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
408                         key.dptr = keystr;
409                         key.dsize = strlen (keystr) + 1;
410                         if (!tdb_delete(mangle_tdb, key))
411                         {
412                                 DEBUG(0, ("mangle: severe error, mangled tdb may be inconsistent!\n"));
413                         }
414                         goto done;
415                 }
416
417                 tclock = False;
418                 tdb_chainunlock(mangle_tdb, klock);
419         }
420         else /* FOUND */
421         {
422                 p = acnv_dosu2(data.dptr);
423                 if (!p)
424                 {
425                         DEBUG(0,("mangle: out of memory!\n"));
426                         goto done;
427                 }
428         }
429                 
430         if (ext)
431         {
432                 pref_len = strlen_w(p);
433                 ext_len = strlen_w(ext);
434                 mangled = (smb_ucs2_t *)malloc((pref_len + ext_len + 2)*sizeof(smb_ucs2_t));
435                 if (!mangled)
436                 {
437                         DEBUG(0,("mangle: out of memory!\n"));
438                         goto done;
439                 }
440                 strncpy_w (mangled, p, pref_len);
441                 mangled[pref_len] = UCS2_CHAR('.');
442                 mangled[pref_len + 1] = 0;
443                 strncat_w (mangled, ext, ext_len);
444         }
445         else
446         {
447                 mangled = strdup_w(p);
448                 if (!mangled)
449                 {
450                         DEBUG(0,("mangle: out of memory!\n"));
451                         goto done;
452                 }
453         }
454
455         /* mangled name are returned in upper or lower case depending on
456            case_default value */
457         strnorm_w(mangled);
458
459 done:
460         if (tclock) tdb_chainunlock(mangle_tdb, klock);
461         SAFE_FREE(p);
462         SAFE_FREE(umpref);
463         SAFE_FREE(ext);
464
465         return mangled;
466 }
467
468
469 /* non unicode compatibility functions */
470
471 char *dos_mangle(const char *dos_unmangled)
472 {
473         smb_ucs2_t *in, *out;
474         char *dos_mangled;
475
476         if (!dos_unmangled || !*dos_unmangled) return NULL;
477
478         in = acnv_dosu2(dos_unmangled);
479         if (!in)
480         {
481                 DEBUG(0,("dos_mangle: out of memory!\n"));
482                 return NULL;
483         }
484
485         out = mangle(in);
486         if (!out)
487         {
488                 SAFE_FREE(in);
489                 return NULL;
490         }
491
492         dos_mangled = acnv_u2dos(out);
493         if (!dos_mangled)
494         {
495                 DEBUG(0,("dos_mangle: out of memory!\n"));
496                 goto done;
497         }
498
499 done:
500         SAFE_FREE(in);
501         SAFE_FREE(out);
502         return dos_mangled;
503 }
504
505 char *dos_unmangle(const char *dos_mangled)
506 {
507         smb_ucs2_t *in, *out;
508         char *dos_unmangled;
509
510         if (!dos_mangled || !*dos_mangled) return NULL;
511
512         in = acnv_dosu2(dos_mangled);
513         if (!in)
514         {
515                 DEBUG(0,("dos_unmangle: out of memory!\n"));
516                 return NULL;
517         }
518
519         out = mangle(in);
520         if (!out)
521         {
522                 SAFE_FREE(in);
523                 return NULL;
524         }
525
526         dos_unmangled = acnv_u2dos(out);
527         if (!dos_unmangled)
528         {
529                 DEBUG(0,("dos_unmangle: out of memory!\n"));
530                 goto done;
531         }
532
533 done:
534         SAFE_FREE(in);
535         SAFE_FREE(out);
536         return dos_unmangled;
537 }
538
539 BOOL is_8_3(const char *fname, BOOL check_case)
540 {
541         smb_ucs2_t *ucs2name;
542         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
543
544         if (!fname || !*fname) return False;
545
546         DEBUG(10,("is_8_3: testing [%s]\n", fname));
547
548         if (strlen(fname) > 12) return False;
549         
550         ucs2name = acnv_uxu2(fname);
551         if (!ucs2name)
552         {
553                 DEBUG(0,("is_8_3: out of memory!\n"));
554                 goto done;
555         }
556
557         ret = is_8_3_w(ucs2name);
558
559 done:
560         SAFE_FREE(ucs2name);
561
562         DEBUG(10,("is_8_3: returning -> %s\n", NT_STATUS_IS_OK(ret)?"True":"False"));
563
564         if (NT_STATUS_IS_ERR(ret)) return False;
565         else return True;
566 }
567
568 NTSTATUS is_8_3_w(const smb_ucs2_t *fname)
569 {
570         smb_ucs2_t *pref = 0, *ext = 0;
571         size_t plen;
572         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
573
574         if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
575
576         DEBUG(10,("is_8_3_w: testing\n")); /* [%s]\n", fname)); */
577
578         if (strlen_w(fname) > 12) return NT_STATUS_UNSUCCESSFUL;
579         
580         if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
581                 return NT_STATUS_OK;
582
583         if (NT_STATUS_IS_ERR(is_valid_name(fname))) goto done;
584
585         if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext))) goto done;
586         plen = strlen_w(pref);
587         if (plen < 1 || plen > 8) goto done;
588         if (ext) if (strlen_w(ext) > 3) goto done;
589
590         ret = NT_STATUS_OK;
591
592 done:
593         SAFE_FREE(pref);
594         SAFE_FREE(ext);
595         return ret;
596 }
597
598 NTSTATUS has_valid_chars(const smb_ucs2_t *s)
599 {
600         NTSTATUS ret = NT_STATUS_OK;
601
602         if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
603
604         DEBUG(10,("has_valid_chars: testing\n")); /* [%s]\n", s)); */
605         
606         /* CHECK: this should not be necessary if the ms wild chars
607            are not valid in valid.dat  --- simo */
608         if (ms_has_wild_w(s)) return NT_STATUS_UNSUCCESSFUL;
609
610         while (*s) {
611                 if(!isvalid83_w(*s)) return NT_STATUS_UNSUCCESSFUL;
612                 s++;
613         }
614
615         return ret;
616 }
617
618 NTSTATUS is_valid_name(const smb_ucs2_t *fname)
619 {
620         smb_ucs2_t *str, *p;
621         NTSTATUS ret = NT_STATUS_OK;
622
623         if (!fname || !*fname) return NT_STATUS_INVALID_PARAMETER;
624
625         DEBUG(10,("is_valid_name: testing\n")); /* [%s]\n", s)); */
626         
627         ret = has_valid_chars(fname);
628         if (NT_STATUS_IS_ERR(ret)) return ret;
629
630         str = strdup_w(fname);
631         p = strchr_w(str, UCS2_CHAR('.'));
632         if (p) *p = 0;
633         strupper_w(str);
634         p = &(str[1]);
635
636         switch(str[0])
637         {
638         case UCS2_CHAR('A'):
639                 if(strcmp_wa(p, "UX") == 0)
640                         ret = NT_STATUS_UNSUCCESSFUL;
641                 break;
642         case UCS2_CHAR('C'):
643                 if((strcmp_wa(p, "LOCK$") == 0)
644                 || (strcmp_wa(p, "ON") == 0)
645                 || (strcmp_wa(p, "OM1") == 0)
646                 || (strcmp_wa(p, "OM2") == 0)
647                 || (strcmp_wa(p, "OM3") == 0)
648                 || (strcmp_wa(p, "OM4") == 0)
649                 )
650                         ret = NT_STATUS_UNSUCCESSFUL;
651                 break;
652         case UCS2_CHAR('L'):
653                 if((strcmp_wa(p, "PT1") == 0)
654                 || (strcmp_wa(p, "PT2") == 0)
655                 || (strcmp_wa(p, "PT3") == 0)
656                 )
657                         ret = NT_STATUS_UNSUCCESSFUL;
658                 break;
659         case UCS2_CHAR('N'):
660                 if(strcmp_wa(p, "UL") == 0)
661                         ret = NT_STATUS_UNSUCCESSFUL;
662                 break;
663         case UCS2_CHAR('P'):
664                 if(strcmp_wa(p, "RN") == 0)
665                         ret = NT_STATUS_UNSUCCESSFUL;
666                 break;
667         default:
668                 break;
669         }
670
671         SAFE_FREE(str);
672         return ret;
673 }
674
675 BOOL is_mangled(const char *s)
676 {
677         smb_ucs2_t *u2, *res;
678         BOOL ret = False;
679         
680         DEBUG(10,("is_mangled: testing [%s]\n", s));
681         
682         if (!s || !*s) return False;
683         if ((strlen(s) > 12) || (!strchr(s, '~'))) return False;
684         
685         u2 = acnv_dosu2(s);
686         if (!u2)
687         {
688                 DEBUG(0,("is_mangled: out of memory!\n"));
689                 return ret;
690         }
691
692         res = unmangle(u2);
693         if (res) ret = True;
694         SAFE_FREE(res);
695         SAFE_FREE(u2);
696         DEBUG(10,("is_mangled: returning  [%s]\n", ret?"True":"False"));
697         return ret;
698 }
699
700 NTSTATUS is_mangled_w(const smb_ucs2_t *s)
701 {
702         smb_ucs2_t *res;
703         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
704         
705         res = unmangle(s);
706         if (res) ret = NT_STATUS_OK;
707         SAFE_FREE(res);
708         return ret;
709 }
710
711 NTSTATUS path_has_mangled(const smb_ucs2_t *s)
712 {
713         smb_ucs2_t *p, *f, *b;
714         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
715
716         if (!s || !*s) return NT_STATUS_INVALID_PARAMETER;
717
718         p = strdup_w(s);
719         if (!p) return NT_STATUS_NO_MEMORY;
720         trim_string_wa(p, "/", "/");
721         f = b = p;
722         while (b) {
723                 b = strchr_w(f, UCS2_CHAR('/'));
724                 if (b) *b = 0;
725                 if (NT_STATUS_IS_OK(is_mangled_w(f))) {
726                         ret = NT_STATUS_OK;
727                         goto done;
728                 }
729                 f = b + 1;
730         }
731 done:
732         SAFE_FREE(p);
733         return ret;
734 }
735
736 /* backward compatibility functions */
737
738 void reset_mangled_cache(void)
739 {
740         DEBUG(10,("reset_mangled_cache: compatibility function, remove me!\n"));
741 }
742
743 BOOL check_mangled_cache(char *s)
744 {
745         smb_ucs2_t *u2, *res;
746         BOOL ret = False;
747
748         DEBUG(10,("check_mangled_cache: I'm so ugly, please remove me!\n"));
749         DEBUG(10,("check_mangled_cache: testing -> [%s]\n", s));
750
751         if (!s || !*s) return False;
752
753         u2 = acnv_dosu2(s);
754         if (!u2)
755         {
756                 DEBUG(0,("check_mangled_cache: out of memory!\n"));
757                 return ret;
758         }
759
760         res = unmangle(u2);
761         if (res)
762         {
763                 
764                 ucs2_to_dos (s, res, PSTRING_LEN);
765                 /* We MUST change this brainded interface,
766                    we do not know how many chars will be used
767                    in dos so i guess they will be no more than
768                    double the size of the unicode string
769                           ---simo */
770                 DEBUG(10,("check_mangled_cache: returning -> [%s]\n", s));
771                 ret = True;
772         }
773         SAFE_FREE(res);
774         SAFE_FREE(u2);
775         DEBUG(10,("check_mangled_cache: returning -> %s\n", ret?"True":"False"));
776         return ret;
777 }
778
779 void mangle_name_83(char *s)
780 {
781         smb_ucs2_t *u2, *res;
782
783         DEBUG(10,("mangle_name_83: I'm so ugly, please remove me!\n"));
784         DEBUG(10,("mangle_name_83: testing -> [%s]\n", s));
785
786         if (!s || !*s) return;
787         
788         u2 = acnv_dosu2(s);
789         if (!u2)
790         {
791                 DEBUG(0,("mangle_name_83: out of memory!\n"));
792                 return;
793         }
794
795         res = mangle(u2);
796         if (res) ucs2_to_dos (s, res, 13); /* ugly, but must be done this way */
797         DEBUG(10,("mangle_name_83: returning -> [%s]\n", s));
798         SAFE_FREE(res);
799         SAFE_FREE(u2);
800 }
801
802 BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)
803 {
804         DEBUG(10,("name_map_mangle: I'm so ugly, please remove me!\n"));
805
806         if (!need83) return True;
807         /* if (is_8_3(OutName, True)) return True; */
808         /* Warning: we should check for invalid chars in file name and mangle
809            if invalid chars found --simo*/
810
811         mangle_name_83(OutName);
812         return True;
813 }
814
815
816
817 #if 0 /* TEST_MANGLE_CODE */
818
819 #define LONG            "this_is_a_long_file_name"
820 #define LONGM           "this_~01"
821 #define SHORT           "short"
822 #define SHORTM          "short~01"
823 #define EXT1            "ex1"
824 #define EXT2            "e2"
825 #define EXT3            "3"
826 #define EXTFAIL         "longext"
827 #define EXTNULL         ""
828
829 static void unmangle_test (char *name, char *ext)
830 {
831         smb_ucs2_t ucs2_name[2048];
832         smb_ucs2_t *retstr;
833         pstring unix_name;      
834
835         push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE);
836         if (ext)
837         {
838                 strncat_wa(ucs2_name, ".", 1);
839                 strncat_wa(ucs2_name, ext, strlen(ext) + 1);
840         }
841         retstr = unmangle(ucs2_name);
842         if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE);
843         else unix_name[0] = 0;
844         if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name);
845         else printf ("[%s] ---> [%s]\n", name, unix_name);
846         SAFE_FREE(retstr);
847 }
848
849 static void mangle_test (char *name, char *ext)
850 {
851         smb_ucs2_t ucs2_name[2048];
852         smb_ucs2_t *retstr;
853         pstring unix_name;      
854
855         push_ucs2(NULL, ucs2_name, name, sizeof(ucs2_name), STR_TERMINATE);
856         if (ext)
857         {
858                 strncat_wa(ucs2_name, ".", 1);
859                 strncat_wa(ucs2_name, ext, strlen(ext) + 1);
860         }
861         retstr = mangle(ucs2_name);
862         if(retstr) pull_ucs2(NULL, unix_name, retstr, sizeof(unix_name), 0, STR_TERMINATE);
863         else unix_name[0] = 0;
864         if (ext) printf ("[%s.%s] ---> [%s]\n", name, ext, unix_name);
865         else printf ("[%s] ---> [%s]\n", name, unix_name);
866         SAFE_FREE(retstr);
867 }
868
869 void mangle_test_code(void)
870 {
871         init_mangle_tdb();
872
873         /* unmangle every */
874         printf("Unmangle test 1:\n");
875
876         unmangle_test (LONG, NULL);
877         unmangle_test (LONG, EXT1);
878         unmangle_test (LONG, EXT2);
879         unmangle_test (LONG, EXT3);
880         unmangle_test (LONG, EXTFAIL);
881         unmangle_test (LONG, EXTNULL);
882
883         unmangle_test (LONGM, NULL);
884         unmangle_test (LONGM, EXT1);
885         unmangle_test (LONGM, EXT2);
886         unmangle_test (LONGM, EXT3);
887         unmangle_test (LONGM, EXTFAIL);
888         unmangle_test (LONGM, EXTNULL);
889
890         unmangle_test (SHORT, NULL);
891         unmangle_test (SHORT, EXT1);
892         unmangle_test (SHORT, EXT2);
893         unmangle_test (SHORT, EXT3);
894         unmangle_test (SHORT, EXTFAIL);
895         unmangle_test (SHORT, EXTNULL);
896
897         unmangle_test (SHORTM, NULL);
898         unmangle_test (SHORTM, EXT1);
899         unmangle_test (SHORTM, EXT2);
900         unmangle_test (SHORTM, EXT3);
901         unmangle_test (SHORTM, EXTFAIL);
902         unmangle_test (SHORTM, EXTNULL);
903
904         /* mangle every */
905         printf("Mangle test\n");
906
907         mangle_test (LONG, NULL);
908         mangle_test (LONG, EXT1);
909         mangle_test (LONG, EXT2);
910         mangle_test (LONG, EXT3);
911         mangle_test (LONG, EXTFAIL);
912         mangle_test (LONG, EXTNULL);
913
914         mangle_test (LONGM, NULL);
915         mangle_test (LONGM, EXT1);
916         mangle_test (LONGM, EXT2);
917         mangle_test (LONGM, EXT3);
918         mangle_test (LONGM, EXTFAIL);
919         mangle_test (LONGM, EXTNULL);
920
921         mangle_test (SHORT, NULL);
922         mangle_test (SHORT, EXT1);
923         mangle_test (SHORT, EXT2);
924         mangle_test (SHORT, EXT3);
925         mangle_test (SHORT, EXTFAIL);
926         mangle_test (SHORT, EXTNULL);
927
928         mangle_test (SHORTM, NULL);
929         mangle_test (SHORTM, EXT1);
930         mangle_test (SHORTM, EXT2);
931         mangle_test (SHORTM, EXT3);
932         mangle_test (SHORTM, EXTFAIL);
933         mangle_test (SHORTM, EXTNULL);
934
935         /* unmangle again every */
936         printf("Unmangle test 2:\n");
937
938         unmangle_test (LONG, NULL);
939         unmangle_test (LONG, EXT1);
940         unmangle_test (LONG, EXT2);
941         unmangle_test (LONG, EXT3);
942         unmangle_test (LONG, EXTFAIL);
943         unmangle_test (LONG, EXTNULL);
944
945         unmangle_test (LONGM, NULL);
946         unmangle_test (LONGM, EXT1);
947         unmangle_test (LONGM, EXT2);
948         unmangle_test (LONGM, EXT3);
949         unmangle_test (LONGM, EXTFAIL);
950         unmangle_test (LONGM, EXTNULL);
951
952         unmangle_test (SHORT, NULL);
953         unmangle_test (SHORT, EXT1);
954         unmangle_test (SHORT, EXT2);
955         unmangle_test (SHORT, EXT3);
956         unmangle_test (SHORT, EXTFAIL);
957         unmangle_test (SHORT, EXTNULL);
958
959         unmangle_test (SHORTM, NULL);
960         unmangle_test (SHORTM, EXT1);
961         unmangle_test (SHORTM, EXT2);
962         unmangle_test (SHORTM, EXT3);
963         unmangle_test (SHORTM, EXTFAIL);
964         unmangle_test (SHORTM, EXTNULL);
965 }
966
967 #endif /* TEST_MANGLE_CODE */