2949d7d795e8f76f975f1eb4074d41845dfa0743
[samba.git] / source3 / lib / util_unistr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-2001
5    Copyright (C) Simo Sorce 2001
6    Copyright (C) Jeremy Allison 2005
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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23
24 #ifndef MAXUNI
25 #define MAXUNI 1024
26 #endif
27
28 /* these 3 tables define the unicode case handling.  They are loaded
29    at startup either via mmap() or read() from the lib directory */
30 static smb_ucs2_t *upcase_table;
31 static smb_ucs2_t *lowcase_table;
32 static uint8 *valid_table;
33 static bool upcase_table_use_unmap;
34 static bool lowcase_table_use_unmap;
35 static bool valid_table_use_unmap;
36
37 /**
38  * This table says which Unicode characters are valid dos
39  * characters.
40  *
41  * Each value is just a single bit.
42  **/
43 static uint8 doschar_table[8192]; /* 65536 characters / 8 bits/byte */
44
45 /**
46  * Destroy global objects allocated by load_case_tables()
47  **/
48 void gfree_case_tables(void)
49 {
50         if ( upcase_table ) {
51                 if ( upcase_table_use_unmap )
52                         unmap_file(upcase_table, 0x20000);
53                 else
54                         SAFE_FREE(upcase_table);
55         }
56
57         if ( lowcase_table ) {
58                 if ( lowcase_table_use_unmap )
59                         unmap_file(lowcase_table, 0x20000);
60                 else
61                         SAFE_FREE(lowcase_table);
62         }
63
64         if ( valid_table ) {
65                 if ( valid_table_use_unmap )
66                         unmap_file(valid_table, 0x10000);
67                 else
68                         SAFE_FREE(valid_table);
69         }
70 }
71
72 /**
73  * Load or generate the case handling tables.
74  *
75  * The case tables are defined in UCS2 and don't depend on any
76  * configured parameters, so they never need to be reloaded.
77  **/
78
79 void load_case_tables(void)
80 {
81         static int initialised;
82         char *old_locale = NULL, *saved_locale = NULL;
83         int i;
84         TALLOC_CTX *frame = NULL;
85
86         if (initialised) {
87                 return;
88         }
89         initialised = 1;
90
91         frame = talloc_stackframe();
92
93         upcase_table = (smb_ucs2_t *)map_file(data_path("upcase.dat"),
94                                               0x20000);
95         upcase_table_use_unmap = ( upcase_table != NULL );
96
97         lowcase_table = (smb_ucs2_t *)map_file(data_path("lowcase.dat"),
98                                                0x20000);
99         lowcase_table_use_unmap = ( lowcase_table != NULL );
100
101 #ifdef HAVE_SETLOCALE
102         /* Get the name of the current locale.  */
103         old_locale = setlocale(LC_ALL, NULL);
104
105         if (old_locale) {
106                 /* Save it as it is in static storage. */
107                 saved_locale = SMB_STRDUP(old_locale);
108         }
109
110         /* We set back the locale to C to get ASCII-compatible toupper/lower functions. */
111         setlocale(LC_ALL, "C");
112 #endif
113
114         /* we would like Samba to limp along even if these tables are
115            not available */
116         if (!upcase_table) {
117                 DEBUG(1,("creating lame upcase table\n"));
118                 upcase_table = (smb_ucs2_t *)SMB_MALLOC(0x20000);
119                 for (i=0;i<0x10000;i++) {
120                         smb_ucs2_t v;
121                         SSVAL(&v, 0, i);
122                         upcase_table[v] = i;
123                 }
124                 for (i=0;i<256;i++) {
125                         smb_ucs2_t v;
126                         SSVAL(&v, 0, UCS2_CHAR(i));
127                         upcase_table[v] = UCS2_CHAR(islower(i)?toupper(i):i);
128                 }
129         }
130
131         if (!lowcase_table) {
132                 DEBUG(1,("creating lame lowcase table\n"));
133                 lowcase_table = (smb_ucs2_t *)SMB_MALLOC(0x20000);
134                 for (i=0;i<0x10000;i++) {
135                         smb_ucs2_t v;
136                         SSVAL(&v, 0, i);
137                         lowcase_table[v] = i;
138                 }
139                 for (i=0;i<256;i++) {
140                         smb_ucs2_t v;
141                         SSVAL(&v, 0, UCS2_CHAR(i));
142                         lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i);
143                 }
144         }
145
146 #ifdef HAVE_SETLOCALE
147         /* Restore the old locale. */
148         if (saved_locale) {
149                 setlocale (LC_ALL, saved_locale);
150                 SAFE_FREE(saved_locale);
151         }
152 #endif
153         TALLOC_FREE(frame);
154 }
155
156 /*
157   see if a ucs2 character can be mapped correctly to a dos character
158   and mapped back to the same character in ucs2
159 */
160
161 static int check_dos_char(smb_ucs2_t c)
162 {
163         lazy_initialize_conv();
164
165         /* Find the right byte, and right bit within the byte; return
166          * 1 or 0 */
167         return (doschar_table[(c & 0xffff) / 8] & (1 << (c & 7))) != 0;
168 }
169
170
171 static int check_dos_char_slowly(smb_ucs2_t c)
172 {
173         char buf[10];
174         smb_ucs2_t c2 = 0;
175         int len1, len2;
176
177         len1 = convert_string(CH_UTF16LE, CH_DOS, &c, 2, buf, sizeof(buf),False);
178         if (len1 == 0) {
179                 return 0;
180         }
181         len2 = convert_string(CH_DOS, CH_UTF16LE, buf, len1, &c2, 2,False);
182         if (len2 != 2) {
183                 return 0;
184         }
185         return (c == c2);
186 }
187
188
189 /**
190  * Fill out doschar table the hard way, by examining each character
191  **/
192
193 static void init_doschar_table(void)
194 {
195         int i, j, byteval;
196
197         /* For each byte of packed table */
198         
199         for (i = 0; i <= 0xffff; i += 8) {
200                 byteval = 0;
201                 for (j = 0; j <= 7; j++) {
202                         smb_ucs2_t c;
203
204                         c = i + j;
205                         
206                         if (check_dos_char_slowly(c)) {
207                                 byteval |= 1 << j;
208                         }
209                 }
210                 doschar_table[i/8] = byteval;
211         }
212 }
213
214
215 /**
216  * Load the valid character map table from <tt>valid.dat</tt> or
217  * create from the configured codepage.
218  *
219  * This function is called whenever the configuration is reloaded.
220  * However, the valid character table is not changed if it's loaded
221  * from a file, because we can't unmap files.
222  **/
223
224 void init_valid_table(void)
225 {
226         static int mapped_file;
227         int i;
228         const char *allowed = ".!#$%&'()_-@^`~";
229         uint8 *valid_file;
230
231         init_doschar_table();
232
233         if (mapped_file) {
234                 /* Can't unmap files, so stick with what we have */
235                 return;
236         }
237
238         valid_file = (uint8 *)map_file(data_path("valid.dat"), 0x10000);
239         if (valid_file) {
240                 valid_table = valid_file;
241                 mapped_file = 1;
242                 valid_table_use_unmap = True;
243                 return;
244         }
245
246         /* Otherwise, we're using a dynamically created valid_table.
247          * It might need to be regenerated if the code page changed.
248          * We know that we're not using a mapped file, so we can
249          * free() the old one. */
250         SAFE_FREE(valid_table);
251
252         /* use free rather than unmap */
253         valid_table_use_unmap = False;
254
255         DEBUG(2,("creating default valid table\n"));
256         valid_table = (uint8 *)SMB_MALLOC(0x10000);
257         SMB_ASSERT(valid_table != NULL);
258         for (i=0;i<128;i++) {
259                 valid_table[i] = isalnum(i) || strchr(allowed,i);
260         }
261         
262         for (;i<0x10000;i++) {
263                 smb_ucs2_t c;
264                 SSVAL(&c, 0, i);
265                 valid_table[i] = check_dos_char(c);
266         }
267 }
268
269 /*******************************************************************
270  Write a string in (little-endian) unicode format. src is in
271  the current DOS codepage. len is the length in bytes of the
272  string pointed to by dst.
273
274  if null_terminate is True then null terminate the packet (adds 2 bytes)
275
276  the return value is the length in bytes consumed by the string, including the
277  null termination if applied
278 ********************************************************************/
279
280 size_t dos_PutUniCode(char *dst,const char *src, size_t len, bool null_terminate)
281 {
282         int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
283                                    : STR_UNICODE|STR_NOALIGN;
284         return push_ucs2(NULL, dst, src, len, flags);
285 }
286
287
288 /*******************************************************************
289  Skip past a unicode string, but not more than len. Always move
290  past a terminating zero if found.
291 ********************************************************************/
292
293 char *skip_unibuf(char *src, size_t len)
294 {
295         char *srcend = src + len;
296
297         while (src < srcend && SVAL(src,0)) {
298                 src += 2;
299         }
300
301         if(!SVAL(src,0)) {
302                 src += 2;
303         }
304
305         return src;
306 }
307
308 /* Copy a string from little-endian or big-endian unicode source (depending
309  * on flags) to internal samba format destination
310  */ 
311
312 int rpcstr_pull(char* dest, void *src, int dest_len, int src_len, int flags)
313 {
314         if (!src) {
315                 dest[0] = 0;
316                 return 0;
317         }
318         if(dest_len==-1) {
319                 dest_len=MAXUNI-3;
320         }
321         return pull_ucs2(NULL, dest, src, dest_len, src_len, flags|STR_UNICODE|STR_NOALIGN);
322 }
323
324 /* Copy a string from little-endian or big-endian unicode source (depending
325  * on flags) to internal samba format destination. Allocates on talloc ctx.
326  */
327
328 int rpcstr_pull_talloc(TALLOC_CTX *ctx,
329                         char **dest,
330                         void *src,
331                         int src_len,
332                         int flags)
333 {
334         return pull_ucs2_base_talloc(ctx,
335                         NULL,
336                         dest,
337                         src,
338                         src_len,
339                         flags|STR_UNICODE|STR_NOALIGN);
340
341 }
342
343 /* Copy a string from a unistr2 source to internal samba format
344    destination.  Use this instead of direct calls to rpcstr_pull() to avoid
345    having to determine whether the source string is null terminated. */
346
347 int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
348 {
349         return pull_ucs2(NULL, dest, src->buffer, sizeof(fstring),
350                          src->uni_str_len * 2, 0);
351 }
352
353 /* Helper function to return a talloc'ed string. I have implemented it with a
354  * copy because I don't really know how pull_ucs2 and friends calculate the
355  * target size. If this turns out to be a major bottleneck someone with deeper
356  * multi-byte knowledge needs to revisit this.
357  * I just did (JRA :-). No longer uses copy.
358  * My (VL) use is dsr_getdcname, which returns 6 strings, the alternative would
359  * have been to manually talloc_strdup them in rpc_client/cli_netlogon.c.
360  */
361
362 char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *ctx, const UNISTR2 *src)
363 {
364         char *dest = NULL;
365         size_t dest_len = convert_string_talloc(ctx,
366                                 CH_UTF16LE,
367                                 CH_UNIX,
368                                 src->buffer,
369                                 src->uni_str_len * 2,
370                                 (void *)&dest,
371                                 true);
372         if (dest_len == (size_t)-1) {
373                 return NULL;
374         }
375
376         /* Ensure we're returning a null terminated string. */
377         if (dest_len) {
378                 /* Did we already process the terminating zero ? */
379                 if (dest[dest_len-1] != 0) {
380                         size_t size = talloc_get_size(dest);
381                         /* Have we got space to append the '\0' ? */
382                         if (size <= dest_len) {
383                                 /* No, realloc. */
384                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
385                                                 dest_len+1);
386                                 if (!dest) {
387                                         /* talloc fail. */
388                                         dest_len = (size_t)-1;
389                                         return NULL;
390                                 }
391                         }
392                         /* Yay - space ! */
393                         dest[dest_len] = '\0';
394                         dest_len++;
395                 }
396         } else if (dest) {
397                 dest[0] = 0;
398         }
399
400         return dest;
401 }
402
403 /* Converts a string from internal samba format to unicode
404  */
405
406 int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags)
407 {
408         return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
409 }
410
411 /* Converts a string from internal samba format to unicode. Always terminates.
412  * Actually just a wrapper round push_ucs2_talloc().
413  */
414
415 int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
416 {
417         return push_ucs2_talloc(ctx, dest, src);
418 }
419
420 /*******************************************************************
421  Convert a (little-endian) UNISTR2 structure to an ASCII string.
422 ********************************************************************/
423
424 void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
425 {
426         if ((str == NULL) || (str->uni_str_len == 0)) {
427                 *dest='\0';
428                 return;
429         }
430         pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN);
431 }
432
433 #if 0
434 /*******************************************************************
435  Convert a (little-endian) UNISTR3 structure to an ASCII string.
436 ********************************************************************/
437
438 void unistr3_to_ascii(char *dest, const UNISTR3 *str, size_t maxlen)
439 {
440         if ((str == NULL) || (str->uni_str_len == 0)) {
441                 *dest='\0';
442                 return;
443         }
444         pull_ucs2(NULL, dest, str->str.buffer, maxlen, str->uni_str_len*2,
445                   STR_NOALIGN);
446 }
447 #endif
448
449 /*******************************************************************
450  Duplicate a UNISTR2 string into a null terminated char*
451  using a talloc context.
452 ********************************************************************/
453
454 char *unistr2_to_ascii_talloc(TALLOC_CTX *ctx, const UNISTR2 *str)
455 {
456         char *s = NULL;
457
458         if (!str || !str->buffer) {
459                 return NULL;
460         }
461         if (pull_ucs2_base_talloc(ctx,
462                                 NULL,
463                                 &s,
464                                 str->buffer,
465                                 str->uni_str_len*2,
466                                 STR_NOALIGN) == (size_t)-1) {
467                 return NULL;
468         }
469         return s;
470 }
471
472 /*******************************************************************
473  Return a string for displaying a UNISTR2. Guarentees to return a
474  valid string - "" if nothing else.
475  Changed to use talloc_tos() under the covers.... JRA.
476 ********************************************************************/
477
478 const char *unistr2_static(const UNISTR2 *str)
479 {
480         char *dest = NULL;
481
482         if ((str == NULL) || (str->uni_str_len == 0)) {
483                 return "";
484         }
485
486         dest = unistr2_to_ascii_talloc(talloc_tos(), str);
487         if (!dest) {
488                 return "";
489         }
490
491         return dest;
492 }
493
494 /*******************************************************************
495  Convert a wchar to upper case.
496 ********************************************************************/
497
498 smb_ucs2_t toupper_w(smb_ucs2_t val)
499 {
500         return upcase_table[SVAL(&val,0)];
501 }
502
503 /*******************************************************************
504  Convert a wchar to lower case.
505 ********************************************************************/
506
507 smb_ucs2_t tolower_w( smb_ucs2_t val )
508 {
509         return lowcase_table[SVAL(&val,0)];
510 }
511
512 /*******************************************************************
513  Determine if a character is lowercase.
514 ********************************************************************/
515
516 bool islower_w(smb_ucs2_t c)
517 {
518         return upcase_table[SVAL(&c,0)] != c;
519 }
520
521 /*******************************************************************
522  Determine if a character is uppercase.
523 ********************************************************************/
524
525 bool isupper_w(smb_ucs2_t c)
526 {
527         return lowcase_table[SVAL(&c,0)] != c;
528 }
529
530 /*******************************************************************
531  Determine if a character is valid in a 8.3 name.
532 ********************************************************************/
533
534 bool isvalid83_w(smb_ucs2_t c)
535 {
536         return valid_table[SVAL(&c,0)] != 0;
537 }
538
539 /*******************************************************************
540  Count the number of characters in a smb_ucs2_t string.
541 ********************************************************************/
542
543 size_t strlen_w(const smb_ucs2_t *src)
544 {
545         size_t len;
546         smb_ucs2_t c;
547
548         for(len = 0; *(COPY_UCS2_CHAR(&c,src)); src++, len++) {
549                 ;
550         }
551
552         return len;
553 }
554
555 /*******************************************************************
556  Count up to max number of characters in a smb_ucs2_t string.
557 ********************************************************************/
558
559 size_t strnlen_w(const smb_ucs2_t *src, size_t max)
560 {
561         size_t len;
562         smb_ucs2_t c;
563
564         for(len = 0; (len < max) && *(COPY_UCS2_CHAR(&c,src)); src++, len++) {
565                 ;
566         }
567
568         return len;
569 }
570
571 /*******************************************************************
572  Wide strchr().
573 ********************************************************************/
574
575 smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
576 {
577         smb_ucs2_t cp;
578         while (*(COPY_UCS2_CHAR(&cp,s))) {
579                 if (c == cp) {
580                         return (smb_ucs2_t *)s;
581                 }
582                 s++;
583         }
584         if (c == cp) {
585                 return (smb_ucs2_t *)s;
586         }
587
588         return NULL;
589 }
590
591 smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)
592 {
593         return strchr_w(s, UCS2_CHAR(c));
594 }
595
596 /*******************************************************************
597  Wide strrchr().
598 ********************************************************************/
599
600 smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
601 {
602         smb_ucs2_t cp;
603         const smb_ucs2_t *p = s;
604         int len = strlen_w(s);
605
606         if (len == 0) {
607                 return NULL;
608         }
609         p += (len - 1);
610         do {
611                 if (c == *(COPY_UCS2_CHAR(&cp,p))) {
612                         return (smb_ucs2_t *)p;
613                 }
614         } while (p-- != s);
615         return NULL;
616 }
617
618 /*******************************************************************
619  Wide version of strrchr that returns after doing strrchr 'n' times.
620 ********************************************************************/
621
622 smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n)
623 {
624         smb_ucs2_t cp;
625         const smb_ucs2_t *p = s;
626         int len = strlen_w(s);
627
628         if (len == 0 || !n) {
629                 return NULL;
630         }
631         p += (len - 1);
632         do {
633                 if (c == *(COPY_UCS2_CHAR(&cp,p))) {
634                         n--;
635                 }
636
637                 if (!n) {
638                         return (smb_ucs2_t *)p;
639                 }
640         } while (p-- != s);
641         return NULL;
642 }
643
644 /*******************************************************************
645  Wide strstr().
646 ********************************************************************/
647
648 smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
649 {
650         smb_ucs2_t *r;
651         size_t inslen;
652
653         if (!s || !*s || !ins || !*ins) {
654                 return NULL;
655         }
656
657         inslen = strlen_w(ins);
658         r = (smb_ucs2_t *)s;
659
660         while ((r = strchr_w(r, *ins))) {
661                 if (strncmp_w(r, ins, inslen) == 0) {
662                         return r;
663                 }
664                 r++;
665         }
666
667         return NULL;
668 }
669
670 /*******************************************************************
671  Convert a string to lower case.
672  return True if any char is converted
673 ********************************************************************/
674
675 bool strlower_w(smb_ucs2_t *s)
676 {
677         smb_ucs2_t cp;
678         bool ret = False;
679
680         while (*(COPY_UCS2_CHAR(&cp,s))) {
681                 smb_ucs2_t v = tolower_w(cp);
682                 if (v != cp) {
683                         COPY_UCS2_CHAR(s,&v);
684                         ret = True;
685                 }
686                 s++;
687         }
688         return ret;
689 }
690
691 /*******************************************************************
692  Convert a string to upper case.
693  return True if any char is converted
694 ********************************************************************/
695
696 bool strupper_w(smb_ucs2_t *s)
697 {
698         smb_ucs2_t cp;
699         bool ret = False;
700         while (*(COPY_UCS2_CHAR(&cp,s))) {
701                 smb_ucs2_t v = toupper_w(cp);
702                 if (v != cp) {
703                         COPY_UCS2_CHAR(s,&v);
704                         ret = True;
705                 }
706                 s++;
707         }
708         return ret;
709 }
710
711 /*******************************************************************
712  Convert a string to "normal" form.
713 ********************************************************************/
714
715 void strnorm_w(smb_ucs2_t *s, int case_default)
716 {
717         if (case_default == CASE_UPPER) {
718                 strupper_w(s);
719         } else {
720                 strlower_w(s);
721         }
722 }
723
724 int strcmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
725 {
726         smb_ucs2_t cpa, cpb;
727
728         while ((*(COPY_UCS2_CHAR(&cpb,b))) && (*(COPY_UCS2_CHAR(&cpa,a)) == cpb)) {
729                 a++;
730                 b++;
731         }
732         return (*(COPY_UCS2_CHAR(&cpa,a)) - *(COPY_UCS2_CHAR(&cpb,b)));
733         /* warning: if *a != *b and both are not 0 we return a random
734                 greater or lesser than 0 number not realted to which
735                 string is longer */
736 }
737
738 int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
739 {
740         smb_ucs2_t cpa, cpb;
741         size_t n = 0;
742
743         while ((n < len) && (*(COPY_UCS2_CHAR(&cpb,b))) && (*(COPY_UCS2_CHAR(&cpa,a)) == cpb)) {
744                 a++;
745                 b++;
746                 n++;
747         }
748         return (len - n)?(*(COPY_UCS2_CHAR(&cpa,a)) - *(COPY_UCS2_CHAR(&cpb,b))):0;
749 }
750
751 /*******************************************************************
752  Case insensitive string comparison.
753 ********************************************************************/
754
755 int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
756 {
757         smb_ucs2_t cpa, cpb;
758
759         while ((*COPY_UCS2_CHAR(&cpb,b)) && toupper_w(*(COPY_UCS2_CHAR(&cpa,a))) == toupper_w(cpb)) {
760                 a++;
761                 b++;
762         }
763         return (tolower_w(*(COPY_UCS2_CHAR(&cpa,a))) - tolower_w(*(COPY_UCS2_CHAR(&cpb,b))));
764 }
765
766 /*******************************************************************
767  Case insensitive string comparison, length limited.
768 ********************************************************************/
769
770 int strncasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
771 {
772         smb_ucs2_t cpa, cpb;
773         size_t n = 0;
774
775         while ((n < len) && *COPY_UCS2_CHAR(&cpb,b) && (toupper_w(*(COPY_UCS2_CHAR(&cpa,a))) == toupper_w(cpb))) {
776                 a++;
777                 b++;
778                 n++;
779         }
780         return (len - n)?(tolower_w(*(COPY_UCS2_CHAR(&cpa,a))) - tolower_w(*(COPY_UCS2_CHAR(&cpb,b)))):0;
781 }
782
783 /*******************************************************************
784  Compare 2 strings.
785 ********************************************************************/
786
787 bool strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
788 {
789         if (s1 == s2) {
790                 return(True);
791         }
792         if (!s1 || !s2) {
793                 return(False);
794         }
795   
796         return(strcasecmp_w(s1,s2)==0);
797 }
798
799 /*******************************************************************
800  Compare 2 strings up to and including the nth char.
801 ******************************************************************/
802
803 bool strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
804 {
805         if (s1 == s2) {
806                 return(True);
807         }
808         if (!s1 || !s2 || !n) {
809                 return(False);
810         }
811   
812         return(strncasecmp_w(s1,s2,n)==0);
813 }
814
815 /*******************************************************************
816  Duplicate string.
817 ********************************************************************/
818
819 smb_ucs2_t *strdup_w(const smb_ucs2_t *src)
820 {
821         return strndup_w(src, 0);
822 }
823
824 /* if len == 0 then duplicate the whole string */
825
826 smb_ucs2_t *strndup_w(const smb_ucs2_t *src, size_t len)
827 {
828         smb_ucs2_t *dest;
829         
830         if (!len) {
831                 len = strlen_w(src);
832         }
833         dest = SMB_MALLOC_ARRAY(smb_ucs2_t, len + 1);
834         if (!dest) {
835                 DEBUG(0,("strdup_w: out of memory!\n"));
836                 return NULL;
837         }
838
839         memcpy(dest, src, len * sizeof(smb_ucs2_t));
840         dest[len] = 0;
841         return dest;
842 }
843
844 /*******************************************************************
845  Copy a string with max len.
846 ********************************************************************/
847
848 smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
849 {
850         smb_ucs2_t cp;
851         size_t len;
852         
853         if (!dest || !src) {
854                 return NULL;
855         }
856         
857         for (len = 0; (*COPY_UCS2_CHAR(&cp,(src+len))) && (len < max); len++) {
858                 cp = *COPY_UCS2_CHAR(dest+len,src+len);
859         }
860         cp = 0;
861         for ( /*nothing*/ ; len < max; len++ ) {
862                 cp = *COPY_UCS2_CHAR(dest+len,&cp);
863         }
864         
865         return dest;
866 }
867
868 /*******************************************************************
869  Append a string of len bytes and add a terminator.
870 ********************************************************************/
871
872 smb_ucs2_t *strncat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
873 {       
874         size_t start;
875         size_t len;     
876         smb_ucs2_t z = 0;
877
878         if (!dest || !src) {
879                 return NULL;
880         }
881         
882         start = strlen_w(dest);
883         len = strnlen_w(src, max);
884
885         memcpy(&dest[start], src, len*sizeof(smb_ucs2_t));                      
886         z = *COPY_UCS2_CHAR(dest+start+len,&z);
887
888         return dest;
889 }
890
891 smb_ucs2_t *strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src)
892 {       
893         size_t start;
894         size_t len;     
895         smb_ucs2_t z = 0;
896         
897         if (!dest || !src) {
898                 return NULL;
899         }
900         
901         start = strlen_w(dest);
902         len = strlen_w(src);
903
904         memcpy(&dest[start], src, len*sizeof(smb_ucs2_t));                      
905         z = *COPY_UCS2_CHAR(dest+start+len,&z);
906         
907         return dest;
908 }
909
910
911 /*******************************************************************
912  Replace any occurence of oldc with newc in unicode string.
913 ********************************************************************/
914
915 void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc)
916 {
917         smb_ucs2_t cp;
918
919         for(;*(COPY_UCS2_CHAR(&cp,s));s++) {
920                 if(cp==oldc) {
921                         COPY_UCS2_CHAR(s,&newc);
922                 }
923         }
924 }
925
926 /*******************************************************************
927  Trim unicode string.
928 ********************************************************************/
929
930 bool trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front,
931                                   const smb_ucs2_t *back)
932 {
933         bool ret = False;
934         size_t len, front_len, back_len;
935
936         if (!s) {
937                 return False;
938         }
939
940         len = strlen_w(s);
941
942         if (front && *front) {
943                 front_len = strlen_w(front);
944                 while (len && strncmp_w(s, front, front_len) == 0) {
945                         memmove(s, (s + front_len), (len - front_len + 1) * sizeof(smb_ucs2_t));
946                         len -= front_len;
947                         ret = True;
948                 }
949         }
950         
951         if (back && *back) {
952                 back_len = strlen_w(back);
953                 while (len && strncmp_w((s + (len - back_len)), back, back_len) == 0) {
954                         s[len - back_len] = 0;
955                         len -= back_len;
956                         ret = True;
957                 }
958         }
959
960         return ret;
961 }
962
963 /*
964   The *_wa() functions take a combination of 7 bit ascii
965   and wide characters They are used so that you can use string
966   functions combining C string constants with ucs2 strings
967
968   The char* arguments must NOT be multibyte - to be completely sure
969   of this only pass string constants */
970
971 int strcmp_wa(const smb_ucs2_t *a, const char *b)
972 {
973         smb_ucs2_t cp = 0;
974
975         while (*b && *(COPY_UCS2_CHAR(&cp,a)) == UCS2_CHAR(*b)) {
976                 a++;
977                 b++;
978         }
979         return (*(COPY_UCS2_CHAR(&cp,a)) - UCS2_CHAR(*b));
980 }
981
982 int strncmp_wa(const smb_ucs2_t *a, const char *b, size_t len)
983 {
984         smb_ucs2_t cp = 0;
985         size_t n = 0;
986
987         while ((n < len) && *b && *(COPY_UCS2_CHAR(&cp,a)) == UCS2_CHAR(*b)) {
988                 a++;
989                 b++;
990                 n++;
991         }
992         return (len - n)?(*(COPY_UCS2_CHAR(&cp,a)) - UCS2_CHAR(*b)):0;
993 }
994
995 smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p)
996 {
997         smb_ucs2_t cp;
998
999         while (*(COPY_UCS2_CHAR(&cp,s))) {
1000                 int i;
1001                 for (i=0; p[i] && cp != UCS2_CHAR(p[i]); i++) 
1002                         ;
1003                 if (p[i]) {
1004                         return (smb_ucs2_t *)s;
1005                 }
1006                 s++;
1007         }
1008         return NULL;
1009 }
1010
1011 smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins)
1012 {
1013         smb_ucs2_t *r;
1014         size_t inslen;
1015
1016         if (!s || !ins) { 
1017                 return NULL;
1018         }
1019
1020         inslen = strlen(ins);
1021         r = (smb_ucs2_t *)s;
1022
1023         while ((r = strchr_w(r, UCS2_CHAR(*ins)))) {
1024                 if (strncmp_wa(r, ins, inslen) == 0) 
1025                         return r;
1026                 r++;
1027         }
1028
1029         return NULL;
1030 }
1031
1032 /*******************************************************************
1033  Returns the length in number of wide characters.
1034 ******************************************************************/
1035
1036 int unistrlen(uint16 *s)
1037 {
1038         int len;
1039
1040         if (!s) {
1041                 return -1;
1042         }
1043
1044         for (len=0; SVAL(s,0); s++,len++) {
1045                 ;
1046         }
1047
1048         return len;
1049 }
1050
1051 /*******************************************************************
1052  Strcpy for unicode strings. Returns length (in num of wide chars).
1053  Not odd align safe.
1054 ********************************************************************/
1055
1056 int unistrcpy(uint16 *dst, uint16 *src)
1057 {
1058         int num_wchars = 0;
1059
1060         while (SVAL(src,0)) {
1061                 *dst++ = *src++;
1062                 num_wchars++;
1063         }
1064         *dst = 0;
1065
1066         return num_wchars;
1067 }
1068
1069 /**
1070  * Samba ucs2 type to UNISTR2 conversion
1071  *
1072  * @param ctx Talloc context to create the dst strcture (if null) and the 
1073  *            contents of the unicode string.
1074  * @param dst UNISTR2 destination. If equals null, then it's allocated.
1075  * @param src smb_ucs2_t source.
1076  * @param max_len maximum number of unicode characters to copy. If equals
1077  *        null, then null-termination of src is taken
1078  *
1079  * @return copied UNISTR2 destination
1080  **/
1081
1082 UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src)
1083 {
1084         size_t len;
1085
1086         if (!src) {
1087                 return NULL;
1088         }
1089
1090         len = strlen_w(src);
1091         
1092         /* allocate UNISTR2 destination if not given */
1093         if (!dst) {
1094                 dst = TALLOC_P(ctx, UNISTR2);
1095                 if (!dst)
1096                         return NULL;
1097         }
1098         if (!dst->buffer) {
1099                 dst->buffer = TALLOC_ARRAY(ctx, uint16, len + 1);
1100                 if (!dst->buffer)
1101                         return NULL;
1102         }
1103         
1104         /* set UNISTR2 parameters */
1105         dst->uni_max_len = len + 1;
1106         dst->offset = 0;
1107         dst->uni_str_len = len;
1108         
1109         /* copy the actual unicode string */
1110         strncpy_w(dst->buffer, src, dst->uni_max_len);
1111         
1112         return dst;
1113 }
1114
1115 /*************************************************************
1116  ascii only toupper - saves the need for smbd to be in C locale.
1117 *************************************************************/
1118
1119 int toupper_ascii(int c)
1120 {
1121         smb_ucs2_t uc = toupper_w(UCS2_CHAR(c));
1122         return UCS2_TO_CHAR(uc);
1123 }
1124
1125 /*************************************************************
1126  ascii only tolower - saves the need for smbd to be in C locale.
1127 *************************************************************/
1128
1129 int tolower_ascii(int c)
1130 {
1131         smb_ucs2_t uc = tolower_w(UCS2_CHAR(c));
1132         return UCS2_TO_CHAR(uc);
1133 }
1134
1135 /*************************************************************
1136  ascii only isupper - saves the need for smbd to be in C locale.
1137 *************************************************************/
1138
1139 int isupper_ascii(int c)
1140 {
1141         return isupper_w(UCS2_CHAR(c));
1142 }
1143
1144 /*************************************************************
1145  ascii only islower - saves the need for smbd to be in C locale.
1146 *************************************************************/
1147
1148 int islower_ascii(int c)
1149 {
1150         return islower_w(UCS2_CHAR(c));
1151 }