71ef32a1fd98d48e74eaa0ddef05a7ca93345725
[nivanova/samba-autobuild/.git] / source3 / lib / util_unistr.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Samba utility functions
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26  smb_ucs2_t wchar_list_sep[] = { (smb_ucs2_t)' ', (smb_ucs2_t)'\t', (smb_ucs2_t)',',
27                                                                 (smb_ucs2_t)';', (smb_ucs2_t)':', (smb_ucs2_t)'\n',
28                                                                 (smb_ucs2_t)'\r', 0 };
29 /*
30  * The following are the codepage to ucs2 and vica versa maps.
31  * These are dynamically loaded from a unicode translation file.
32  */
33
34 static smb_ucs2_t *doscp_to_ucs2;
35 static uint16 *ucs2_to_doscp;
36
37 static smb_ucs2_t *unixcp_to_ucs2;
38 static uint16 *ucs2_to_unixcp;
39
40 #ifndef MAXUNI
41 #define MAXUNI 1024
42 #endif
43
44 /*******************************************************************
45  Write a string in (little-endian) unicode format. src is in
46  the current DOS codepage. len is the length in bytes of the
47  string pointed to by dst.
48
49  if null_terminate is True then null terminate the packet (adds 2 bytes)
50
51  the return value is the length consumed by the string, including the
52  null termination if applied
53 ********************************************************************/
54
55 int dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
56 {
57         int ret = 0;
58         while (*src && (len > 2)) {
59                 size_t skip = get_character_len(*src);
60                 smb_ucs2_t val = (*src & 0xff);
61
62                 /*
63                  * If this is a multibyte character (and all DOS/Windows
64                  * codepages have at maximum 2 byte multibyte characters)
65                  * then work out the index value for the unicode conversion.
66                  */
67
68                 if (skip == 2)
69                         val = ((val << 8) | (src[1] & 0xff));
70
71                 SSVAL(dst,ret,doscp_to_ucs2[val]);
72                 ret += 2;
73                 len -= 2;
74                 if (skip)
75                         src += skip;
76                 else
77                         src++;
78         }
79         if (null_terminate) {
80                 SSVAL(dst,ret,0);
81                 ret += 2;
82         }
83         return(ret);
84 }
85
86 /*******************************************************************
87  Put an ASCII string into a UNICODE array (uint16's).
88
89  Warning: doesn't do any codepage !!! BAD !!!
90  
91  Help ! Fix Me ! Fix Me !
92 ********************************************************************/
93
94 void ascii_to_unistr(uint16 *dest, const char *src, int maxlen)
95 {
96         uint16 *destend = dest + maxlen;
97         register char c;
98
99         while (dest < destend)
100         {
101                 c = *(src++);
102                 if (c == 0)
103                 {
104                         break;
105                 }
106
107                 *(dest++) = (uint16)c;
108         }
109
110         *dest = 0;
111 }
112
113 /*******************************************************************
114  Pull an ASCII string out of a UNICODE array (uint16's).
115
116  Warning: doesn't do any codepage !!! BAD !!!
117  
118  Help ! Fix Me ! Fix Me !
119 ********************************************************************/
120
121 void unistr_to_ascii(char *dest, const uint16 *src, int len)
122 {
123         char *destend = dest + len;
124         register uint16 c;
125
126         while (dest < destend)
127         {
128                 c = *(src++);
129                 if (c == 0)
130                 {
131                         break;
132                 }
133
134                 *(dest++) = (char)c;
135         }
136
137         *dest = 0;
138 }
139
140 /*******************************************************************
141  Skip past a unicode string, but not more than len. Always move
142  past a terminating zero if found.
143 ********************************************************************/
144
145 char *skip_unibuf(char *src, size_t len)
146 {
147     char *srcend = src + len;
148
149     while (src < srcend && SVAL(src,0))
150         src += 2;
151
152     if(!SVAL(src,0))
153         src += 2;
154
155     return src;
156 }
157
158 /*******************************************************************
159  Return a DOS codepage version of a little-endian unicode string.
160  len is the filename length (ignoring any terminating zero) in uin16
161  units. Always null terminates.
162  Hack alert: uses fixed buffer(s).
163 ********************************************************************/
164
165 char *dos_unistrn2(uint16 *src, int len)
166 {
167         static char lbufs[8][MAXUNI];
168         static int nexti;
169         char *lbuf = lbufs[nexti];
170         char *p;
171
172         nexti = (nexti+1)%8;
173
174         for (p = lbuf; (len > 0) && (p-lbuf < MAXUNI-3) && *src; len--, src++) {
175                 uint16 ucs2_val = SVAL(src,0);
176                 uint16 cp_val = ucs2_to_doscp[ucs2_val];
177
178                 if (cp_val < 256)
179                         *p++ = (char)cp_val;
180                 else {
181                         *p++ = (cp_val >> 8) & 0xff;
182                         *p++ = (cp_val & 0xff);
183                 }
184         }
185
186         *p = 0;
187         return lbuf;
188 }
189
190 static char lbufs[8][MAXUNI];
191 static int nexti;
192
193 /*******************************************************************
194  Return a DOS codepage version of a little-endian unicode string.
195  Hack alert: uses fixed buffer(s).
196 ********************************************************************/
197
198 char *dos_unistr2(uint16 *src)
199 {
200         char *lbuf = lbufs[nexti];
201         char *p;
202
203         nexti = (nexti+1)%8;
204
205         for (p = lbuf; *src && (p-lbuf < MAXUNI-3); src++) {
206                 uint16 ucs2_val = SVAL(src,0);
207                 uint16 cp_val = ucs2_to_doscp[ucs2_val];
208
209                 if (cp_val < 256)
210                         *p++ = (char)cp_val;
211                 else {
212                         *p++ = (cp_val >> 8) & 0xff;
213                         *p++ = (cp_val & 0xff);
214                 }
215         }
216
217         *p = 0;
218         return lbuf;
219 }
220
221 /*******************************************************************
222 Return a DOS codepage version of a little-endian unicode string
223 ********************************************************************/
224
225 char *dos_unistr2_to_str(UNISTR2 *str)
226 {
227         char *lbuf = lbufs[nexti];
228         char *p;
229         uint16 *src = str->buffer;
230         int max_size = MIN(sizeof(str->buffer)-3, str->uni_str_len);
231
232         nexti = (nexti+1)%8;
233
234         for (p = lbuf; *src && p-lbuf < max_size; src++) {
235                 uint16 ucs2_val = SVAL(src,0);
236                 uint16 cp_val = ucs2_to_doscp[ucs2_val];
237
238                 if (cp_val < 256)
239                         *p++ = (char)cp_val;
240                 else {
241                         *p++ = (cp_val >> 8) & 0xff;
242                         *p++ = (cp_val & 0xff);
243                 }
244         }
245
246         *p = 0;
247         return lbuf;
248 }
249
250 /*******************************************************************
251  Convert a UNISTR2 structure to an ASCII string
252  Warning: this version does DOS codepage.
253 ********************************************************************/
254
255 void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
256 {
257         char *destend;
258         const uint16 *src;
259         size_t len;
260         register uint16 c;
261
262         src = str->buffer;
263         len = MIN(str->uni_str_len, maxlen);
264         destend = dest + len;
265
266         while (dest < destend)
267         {
268                 uint16 ucs2_val;
269                 uint16 cp_val;
270
271                 c = *src;
272                 if (c == 0)
273                 {
274                         break;
275                 }
276                 
277                 ucs2_val = SVAL(src++,0);
278                 cp_val = ucs2_to_doscp[ucs2_val];
279                                 
280                 if (cp_val < 256)
281                         *(dest++) = (char)cp_val;
282                 else {
283                         *dest= (cp_val >> 8) & 0xff;
284                         *(dest++) = (cp_val & 0xff);
285                 }
286         }
287
288         *dest = 0;
289 }
290
291
292 /*******************************************************************
293 Return a number stored in a buffer
294 ********************************************************************/
295
296 uint32 buffer2_to_uint32(BUFFER2 *str)
297 {
298         if (str->buf_len == 4)
299                 return IVAL(str->buffer, 0);
300         else
301                 return 0;
302 }
303
304 /*******************************************************************
305 Return a DOS codepage version of a NOTunicode string
306 ********************************************************************/
307
308 char *dos_buffer2_to_str(BUFFER2 *str)
309 {
310         char *lbuf = lbufs[nexti];
311         char *p;
312         uint16 *src = str->buffer;
313         int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
314
315         nexti = (nexti+1)%8;
316
317         for (p = lbuf; *src && p-lbuf < max_size; src++) {
318                 uint16 ucs2_val = SVAL(src,0);
319                 uint16 cp_val = ucs2_to_doscp[ucs2_val];
320
321                 if (cp_val < 256)
322                         *p++ = (char)cp_val;
323                 else {
324                         *p++ = (cp_val >> 8) & 0xff;
325                         *p++ = (cp_val & 0xff);
326                 }
327         }
328
329         *p = 0;
330         return lbuf;
331 }
332
333 /*******************************************************************
334  Return a dos codepage version of a NOTunicode string
335 ********************************************************************/
336
337 char *dos_buffer2_to_multistr(BUFFER2 *str)
338 {
339         char *lbuf = lbufs[nexti];
340         char *p;
341         uint16 *src = str->buffer;
342         int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
343
344         nexti = (nexti+1)%8;
345
346         for (p = lbuf; p-lbuf < max_size; src++) {
347                 if (*src == 0) {
348                         *p++ = ' ';
349                 } else {
350                         uint16 ucs2_val = SVAL(src,0);
351                         uint16 cp_val = ucs2_to_doscp[ucs2_val];
352
353                         if (cp_val < 256)
354                                 *p++ = (char)cp_val;
355                         else {
356                                 *p++ = (cp_val >> 8) & 0xff;
357                                 *p++ = (cp_val & 0xff);
358                         }
359                 }
360         }
361
362         *p = 0;
363         return lbuf;
364 }
365
366 /*******************************************************************
367  Create a null-terminated unicode string from a null-terminated DOS
368  codepage string.
369  Return number of unicode chars copied, excluding the null character.
370  Unicode strings created are in little-endian format.
371 ********************************************************************/
372
373 size_t dos_struni2(char *dst, const char *src, size_t max_len)
374 {
375         size_t len = 0;
376
377         if (dst == NULL)
378                 return 0;
379
380         if (src != NULL) {
381                 for (; *src && len < max_len-2; len++, dst +=2) {
382                         size_t skip = get_character_len(*src);
383                         smb_ucs2_t val = (*src & 0xff);
384
385                         /*
386                          * If this is a multibyte character (and all DOS/Windows
387                          * codepages have at maximum 2 byte multibyte characters)
388                          * then work out the index value for the unicode conversion.
389                          */
390
391                         if (skip == 2)
392                                 val = ((val << 8) | (src[1] & 0xff));
393
394                         SSVAL(dst,0,doscp_to_ucs2[val]);
395                         if (skip)
396                                 src += skip;
397                         else
398                                 src++;
399                 }
400         }
401
402         SSVAL(dst,0,0);
403
404         return len;
405 }
406
407 /*******************************************************************
408  Return a DOS codepage version of a little-endian unicode string.
409  Hack alert: uses fixed buffer(s).
410 ********************************************************************/
411
412 char *dos_unistr(char *buf)
413 {
414         char *lbuf = lbufs[nexti];
415         uint16 *src = (uint16 *)buf;
416         char *p;
417
418         nexti = (nexti+1)%8;
419
420         for (p = lbuf; *src && p-lbuf < MAXUNI-3; src++) {
421                 uint16 ucs2_val = SVAL(src,0);
422                 uint16 cp_val = ucs2_to_doscp[ucs2_val];
423
424                 if (cp_val < 256)
425                         *p++ = (char)cp_val;
426                 else {
427                         *p++ = (cp_val >> 8) & 0xff;
428                         *p++ = (cp_val & 0xff);
429                 }
430         }
431
432         *p = 0;
433         return lbuf;
434 }
435
436 /*******************************************************************
437  Strcpy for unicode strings.  returns length (in num of wide chars)
438 ********************************************************************/
439
440 int unistrcpy(char *dst, char *src)
441 {
442         int num_wchars = 0;
443         uint16 *wsrc = (uint16 *)src;
444         uint16 *wdst = (uint16 *)dst;
445
446         while (*wsrc) {
447                 *wdst++ = *wsrc++;
448                 num_wchars++;
449         }
450         *wdst = 0;
451
452         return num_wchars;
453 }
454
455
456
457 /*******************************************************************
458  Free any existing maps.
459 ********************************************************************/
460
461 static void free_maps(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
462 {
463         /* this handles identity mappings where we share the pointer */
464         if (*pp_ucs2_to_cp == *pp_cp_to_ucs2) {
465                 *pp_ucs2_to_cp = NULL;
466         }
467
468         if (*pp_cp_to_ucs2) {
469                 free(*pp_cp_to_ucs2);
470                 *pp_cp_to_ucs2 = NULL;
471         }
472
473         if (*pp_ucs2_to_cp) {
474                 free(*pp_ucs2_to_cp);
475                 *pp_ucs2_to_cp = NULL;
476         }
477 }
478
479
480 /*******************************************************************
481  Build a default (null) codepage to unicode map.
482 ********************************************************************/
483
484 void default_unicode_map(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
485 {
486   int i;
487
488   free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
489
490   if ((*pp_ucs2_to_cp = (uint16 *)malloc(2*65536)) == NULL) {
491     DEBUG(0,("default_unicode_map: malloc fail for ucs2_to_cp size %u.\n", 2*65536));
492     abort();
493   }
494
495   *pp_cp_to_ucs2 = *pp_ucs2_to_cp; /* Default map is an identity. */
496   for (i = 0; i < 65536; i++)
497     (*pp_cp_to_ucs2)[i] = i;
498 }
499
500 /*******************************************************************
501  Load a codepage to unicode and vica-versa map.
502 ********************************************************************/
503
504 BOOL load_unicode_map(const char *codepage, smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
505 {
506   pstring unicode_map_file_name;
507   FILE *fp = NULL;
508   SMB_STRUCT_STAT st;
509   smb_ucs2_t *cp_to_ucs2 = *pp_cp_to_ucs2;
510   uint16 *ucs2_to_cp = *pp_ucs2_to_cp;
511   size_t cp_to_ucs2_size;
512   size_t ucs2_to_cp_size;
513   size_t i;
514   size_t size;
515   char buf[UNICODE_MAP_HEADER_SIZE];
516
517   DEBUG(5, ("load_unicode_map: loading unicode map for codepage %s.\n", codepage));
518
519   if (*codepage == '\0')
520     goto clean_and_exit;
521
522   if(strlen(CODEPAGEDIR) + 13 + strlen(codepage) > sizeof(unicode_map_file_name)) {
523     DEBUG(0,("load_unicode_map: filename too long to load\n"));
524     goto clean_and_exit;
525   }
526
527   pstrcpy(unicode_map_file_name, CODEPAGEDIR);
528   pstrcat(unicode_map_file_name, "/");
529   pstrcat(unicode_map_file_name, "unicode_map.");
530   pstrcat(unicode_map_file_name, codepage);
531
532   if(sys_stat(unicode_map_file_name,&st)!=0) {
533     DEBUG(0,("load_unicode_map: filename %s does not exist.\n",
534               unicode_map_file_name));
535     goto clean_and_exit;
536   }
537
538   size = st.st_size;
539
540   if ((size != UNICODE_MAP_HEADER_SIZE + 4*65536) && (size != UNICODE_MAP_HEADER_SIZE +(2*256 + 2*65536))) {
541     DEBUG(0,("load_unicode_map: file %s is an incorrect size for a \
542 unicode map file (size=%d).\n", unicode_map_file_name, (int)size));
543     goto clean_and_exit;
544   }
545
546   if((fp = sys_fopen( unicode_map_file_name, "r")) == NULL) {
547     DEBUG(0,("load_unicode_map: cannot open file %s. Error was %s\n",
548               unicode_map_file_name, strerror(errno)));
549     goto clean_and_exit;
550   }
551
552   if(fread( buf, 1, UNICODE_MAP_HEADER_SIZE, fp)!=UNICODE_MAP_HEADER_SIZE) {
553     DEBUG(0,("load_unicode_map: cannot read header from file %s. Error was %s\n",
554               unicode_map_file_name, strerror(errno)));
555     goto clean_and_exit;
556   }
557
558   /* Check the version value */
559   if(SVAL(buf,UNICODE_MAP_VERSION_OFFSET) != UNICODE_MAP_FILE_VERSION_ID) {
560     DEBUG(0,("load_unicode_map: filename %s has incorrect version id. \
561 Needed %hu, got %hu.\n",
562           unicode_map_file_name, (uint16)UNICODE_MAP_FILE_VERSION_ID,
563           SVAL(buf,UNICODE_MAP_VERSION_OFFSET)));
564     goto clean_and_exit;
565   }
566
567   /* Check the codepage value */
568   if(!strequal(&buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], codepage)) {
569     DEBUG(0,("load_unicode_map: codepage %s in file %s is not the same as that \
570 requested (%s).\n", &buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], unicode_map_file_name, codepage ));
571     goto clean_and_exit;
572   }
573
574   ucs2_to_cp_size = 2*65536;
575   if (size == UNICODE_MAP_HEADER_SIZE + 4*65536) {
576     /* 
577      * This is a multibyte code page.
578      */
579     cp_to_ucs2_size = 2*65536;
580   } else {
581     /*
582      * Single byte code page.
583      */
584     cp_to_ucs2_size = 2*256;
585   }
586
587   /* 
588    * Free any old translation tables.
589    */
590
591   free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
592
593   if ((cp_to_ucs2 = (smb_ucs2_t *)malloc(cp_to_ucs2_size)) == NULL) {
594     DEBUG(0,("load_unicode_map: malloc fail for cp_to_ucs2 size %u.\n", cp_to_ucs2_size ));
595     goto clean_and_exit;
596   }
597
598   if ((ucs2_to_cp = (uint16 *)malloc(ucs2_to_cp_size)) == NULL) {
599     DEBUG(0,("load_unicode_map: malloc fail for ucs2_to_cp size %u.\n", ucs2_to_cp_size ));
600     goto clean_and_exit;
601   }
602
603   if(fread( (char *)cp_to_ucs2, 1, cp_to_ucs2_size, fp)!=cp_to_ucs2_size) {
604     DEBUG(0,("load_unicode_map: cannot read cp_to_ucs2 from file %s. Error was %s\n",
605               unicode_map_file_name, strerror(errno)));
606     goto clean_and_exit;
607   }
608
609   if(fread( (char *)ucs2_to_cp, 1, ucs2_to_cp_size, fp)!=ucs2_to_cp_size) {
610     DEBUG(0,("load_unicode_map: cannot read ucs2_to_cp from file %s. Error was %s\n",
611               unicode_map_file_name, strerror(errno)));
612     goto clean_and_exit;
613   }
614
615   /*
616    * Now ensure the 16 bit values are in the correct endianness.
617    */
618
619   for (i = 0; i < cp_to_ucs2_size/2; i++)
620     cp_to_ucs2[i] = SVAL(cp_to_ucs2,i*2);
621
622   for (i = 0; i < ucs2_to_cp_size/2; i++)
623     ucs2_to_cp[i] = SVAL(ucs2_to_cp,i*2);
624
625   fclose(fp);
626
627   *pp_cp_to_ucs2 = cp_to_ucs2;
628   *pp_ucs2_to_cp = ucs2_to_cp;
629
630   return True;
631
632 clean_and_exit:
633
634   /* pseudo destructor :-) */
635
636   if(fp != NULL)
637     fclose(fp);
638
639   free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
640
641   default_unicode_map(pp_cp_to_ucs2, pp_ucs2_to_cp);
642
643   return False;
644 }
645
646 /*******************************************************************
647  Load a dos codepage to unicode and vica-versa map.
648 ********************************************************************/
649
650 BOOL load_dos_unicode_map(int codepage)
651 {
652   fstring codepage_str;
653
654   slprintf(codepage_str, sizeof(fstring)-1, "%03d", codepage);
655   return load_unicode_map(codepage_str, &doscp_to_ucs2, &ucs2_to_doscp);
656 }
657
658 /*******************************************************************
659  Load a UNIX codepage to unicode and vica-versa map.
660 ********************************************************************/
661
662 BOOL load_unix_unicode_map(const char *unix_char_set)
663 {
664   fstring upper_unix_char_set;
665
666   fstrcpy(upper_unix_char_set, unix_char_set);
667   strupper(upper_unix_char_set);
668   return load_unicode_map(upper_unix_char_set, &unixcp_to_ucs2, &ucs2_to_unixcp);
669 }
670
671 /*******************************************************************
672  The following functions reproduce many of the non-UNICODE standard
673  string functions in Samba.
674 ********************************************************************/
675
676 /*******************************************************************
677  Convert a UNICODE string to multibyte format. Note that the 'src' is in
678  native byte order, not little endian. Always zero terminates.
679  dst_len is in bytes.
680 ********************************************************************/
681
682 static char *unicode_to_multibyte(char *dst, const smb_ucs2_t *src,
683                                   size_t dst_len, const uint16 *ucs2_to_cp)
684 {
685         size_t dst_pos;
686
687         for(dst_pos = 0; *src && (dst_pos < dst_len - 1);) {
688                 smb_ucs2_t val = ucs2_to_cp[*src++];
689                 if(val < 256) {
690                         dst[dst_pos++] = (char)val;
691                 } else {
692
693                         if(dst_pos >= dst_len - 2)
694                                 break;
695
696                         /*
697                          * A 2 byte value is always written as
698                          * high/low into the buffer stream.
699                          */
700
701                         dst[dst_pos++] = (char)((val >> 8) & 0xff);
702                         dst[dst_pos++] = (char)(val & 0xff);
703                 }
704         }       
705
706         dst[dst_pos] = '\0';
707
708         return dst;
709 }
710
711 /*******************************************************************
712  Convert a multibyte string to UNICODE format. Note that the 'dst' is in
713  native byte order, not little endian. Always zero terminates.
714  dst_len is in bytes.
715 ********************************************************************/
716
717 smb_ucs2_t *multibyte_to_unicode(smb_ucs2_t *dst, const char *src,
718                                  size_t dst_len, smb_ucs2_t *cp_to_ucs2)
719 {
720         size_t i;
721
722         dst_len /= sizeof(smb_ucs2_t); /* Convert to smb_ucs2_t units. */
723
724         for(i = 0; (i < (dst_len  - 1)) && src[i];) {
725                 size_t skip = skip_multibyte_char(*src);
726                 smb_ucs2_t val = (*src & 0xff);
727
728                 /*
729                  * If this is a multibyte character
730                  * then work out the index value for the unicode conversion.
731                  */
732
733                 if (skip == 2)
734                         val = ((val << 8) | (src[1] & 0xff));
735
736                 dst[i++] = cp_to_ucs2[val];
737                 if (skip)
738                         src += skip;
739                 else
740                         src++;
741         }
742
743         dst[i] = 0;
744
745         return dst;
746 }
747
748 /*******************************************************************
749  Convert a UNICODE string to multibyte format. Note that the 'src' is in
750  native byte order, not little endian. Always zero terminates.
751  This function may be replaced if the MB  codepage format is an
752  encoded one (ie. utf8, hex). See the code in lib/kanji.c
753  for details. dst_len is in bytes.
754 ********************************************************************/
755
756 char *unicode_to_unix(char *dst, const smb_ucs2_t *src, size_t dst_len)
757 {
758         return unicode_to_multibyte(dst, src, dst_len, ucs2_to_unixcp);
759 }
760
761 /*******************************************************************
762  Convert a UNIX string to UNICODE format. Note that the 'dst' is in
763  native byte order, not little endian. Always zero terminates.
764  This function may be replaced if the UNIX codepage format is a
765  multi-byte one (ie. JIS, SJIS or utf8). See the code in lib/kanji.c
766  for details. dst_len is in bytes, not ucs2 units.
767 ********************************************************************/
768
769 smb_ucs2_t *unix_to_unicode(smb_ucs2_t *dst, const char *src, size_t dst_len)
770 {
771         return multibyte_to_unicode(dst, src, dst_len, unixcp_to_ucs2);
772 }
773
774 /*******************************************************************
775  Convert a UNICODE string to DOS format. Note that the 'src' is in
776  native byte order, not little endian. Always zero terminates. 
777  dst_len is in bytes.
778 ********************************************************************/ 
779
780 char *unicode_to_dos(char *dst, const smb_ucs2_t *src, size_t dst_len)
781 {
782         return unicode_to_multibyte(dst, src, dst_len, ucs2_to_doscp);
783 }
784
785 /*******************************************************************
786  Convert a DOS string to UNICODE format. Note that the 'dst' is in
787  native byte order, not little endian. Always zero terminates.
788  This function may be replaced if the DOS codepage format is a
789  multi-byte one (ie. JIS, SJIS or utf8). See the code in lib/kanji.c
790  for details. dst_len is in bytes, not ucs2 units.
791 ********************************************************************/
792
793 smb_ucs2_t *dos_to_unicode(smb_ucs2_t *dst, const char *src, size_t dst_len)
794 {
795         return multibyte_to_unicode(dst, src, dst_len, doscp_to_ucs2);
796 }
797
798 /*******************************************************************
799  Count the number of characters in a smb_ucs2_t string.
800 ********************************************************************/
801
802 size_t strlen_w(const smb_ucs2_t *src)
803 {
804   size_t len;
805
806   for(len = 0; *src; len++)
807     ;
808
809   return len;
810 }
811
812 /*******************************************************************
813  Safe wstring copy into a known length string. maxlength includes
814  the terminating zero. maxlength is in ucs2 units.
815 ********************************************************************/
816
817 smb_ucs2_t *safe_strcpy_w(smb_ucs2_t *dest,const smb_ucs2_t *src, size_t maxlength)
818 {
819     size_t ucs2_len;
820
821     if (!dest) {
822         DEBUG(0,("ERROR: NULL dest in safe_strcpy_w\n"));
823         return NULL;
824     }
825
826     if (!src) {
827         *dest = 0;
828         return dest;
829     }
830
831         maxlength /= sizeof(smb_ucs2_t);
832
833         ucs2_len = strlen_w(src);
834
835     if (ucs2_len >= maxlength) {
836                 fstring out;
837         DEBUG(0,("ERROR: string overflow by %u bytes in safe_strcpy_w [%.50s]\n",
838                         (unsigned int)((ucs2_len-maxlength)*sizeof(smb_ucs2_t)),
839                         unicode_to_unix(out,src,sizeof(out))) );
840                 ucs2_len = maxlength - 1;
841     }
842
843     memcpy(dest, src, ucs2_len*sizeof(smb_ucs2_t));
844     dest[ucs2_len] = 0;
845     return dest;
846 }
847
848 /*******************************************************************
849  Safe string cat into a string. maxlength includes the terminating zero.
850  maxlength is in ucs2 units.
851 ********************************************************************/
852
853 smb_ucs2_t *safe_strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxlength)
854 {
855     size_t ucs2_src_len, ucs2_dest_len;
856
857     if (!dest) {
858         DEBUG(0,("ERROR: NULL dest in safe_strcat_w\n"));
859         return NULL;
860     }
861
862     if (!src)
863         return dest;
864
865     ucs2_src_len = strlen_w(src);
866     ucs2_dest_len = strlen_w(dest);
867
868     if (ucs2_src_len + ucs2_dest_len >= maxlength) {
869                 fstring out;
870                 int new_len = maxlength - ucs2_dest_len - 1;
871         DEBUG(0,("ERROR: string overflow by %u characters in safe_strcat_w [%.50s]\n",
872                         (unsigned int)(sizeof(smb_ucs2_t)*(ucs2_src_len + ucs2_dest_len - maxlength)),
873                         unicode_to_unix(out,src,sizeof(out))) );
874         ucs2_src_len = (size_t)(new_len > 0 ? new_len : 0);
875     }
876
877     memcpy(&dest[ucs2_dest_len], src, ucs2_src_len*sizeof(smb_ucs2_t));
878     dest[ucs2_dest_len + ucs2_src_len] = 0;
879     return dest;
880 }
881
882 /*******************************************************************
883  Compare the two strings s1 and s2.
884 ********************************************************************/
885
886 int strcmp_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
887 {
888         smb_ucs2_t c1, c2;
889
890         for (;;) {
891                 c1 = *s1++;
892                 c2 = *s2++;
893
894                 if (c1 != c2)
895                         return c1 - c2;
896
897                 if (c1 == 0)
898             return 0;
899     }
900         return 0;
901 }
902
903 /*******************************************************************
904  Compare the first n characters of s1 to s2. len is in ucs2 units.
905 ********************************************************************/
906
907 int strncmp_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2, size_t len)
908 {
909         smb_ucs2_t c1, c2;
910
911         for (; len != 0; --len) {
912                 c1 = *s1++;
913                 c2 = *s2++;
914
915                 if (c1 != c2)
916                         return c1 - c2;
917
918                 if (c1 == 0)
919                         return 0;
920
921     }
922         return 0;
923 }
924
925 /*******************************************************************
926  Search string s2 from s1.
927 ********************************************************************/
928
929 smb_ucs2_t *strstr_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
930 {
931         size_t len = strlen_w(s2);
932
933         if (!*s2)
934                 return (smb_ucs2_t *)s1;
935
936         for(;*s1; s1++) {
937                 if (*s1 == *s2) {
938                         if (strncmp_w(s1, s2, len) == 0)
939                                 return (smb_ucs2_t *)s1;
940                 }
941         }
942         return NULL; 
943 }
944
945 /*******************************************************************
946  Search for ucs2 char c from the beginning of s.
947 ********************************************************************/ 
948
949 smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
950 {
951         do {
952                 if (*s == c)
953                         return (smb_ucs2_t *)s;
954         } while (*s++);
955
956         return NULL;
957 }
958
959 /*******************************************************************
960  Search for ucs2 char c from the end of s.
961 ********************************************************************/ 
962
963 smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
964 {
965         smb_ucs2_t *retval = 0;
966
967         do {
968                 if (*s == c)
969                         retval = (smb_ucs2_t *)s;
970         } while (*s++);
971
972         return retval;
973 }
974
975 /*******************************************************************
976  Search token from s1 separated by any ucs2 char of s2.
977 ********************************************************************/
978
979 smb_ucs2_t *strtok_w(smb_ucs2_t *s1, const smb_ucs2_t *s2)
980 {
981         static smb_ucs2_t *s = NULL;
982         smb_ucs2_t *q;
983
984         if (!s1) {
985                 if (!s)
986                         return NULL;
987                 s1 = s;
988         }
989
990         for (q = s1; *s1; s1++) {
991                 smb_ucs2_t *p = strchr_w(s2, *s1);
992                 if (p) {
993                         if (s1 != q) {
994                                 s = s1 + 1;
995                                 *s1 = '\0';
996                                 return q;
997                         }
998                         q = s1 + 1;
999                 }
1000         }
1001
1002         s = NULL;
1003         if (*q)
1004                 return q;
1005
1006         return NULL;
1007 }
1008
1009 /*******************************************************************
1010  Duplicate a ucs2 string.
1011 ********************************************************************/
1012
1013 smb_ucs2_t *strdup_w(const smb_ucs2_t *s)
1014 {
1015         size_t newlen = (strlen_w(s)+1)*sizeof(smb_ucs2_t);
1016         smb_ucs2_t *newstr = (smb_ucs2_t *)malloc(newlen);
1017     if (newstr == NULL)
1018         return NULL;
1019     safe_strcpy_w(newstr, s, newlen);
1020     return newstr;
1021 }
1022
1023 /*******************************************************************
1024  Mapping tables for UNICODE character. Allows toupper/tolower and
1025  isXXX functions to work.
1026
1027  tridge: split into 2 pieces. This saves us 5/6 of the memory
1028  with a small speed penalty
1029  The magic constants are the lower/upper range of the tables two
1030  parts
1031 ********************************************************************/
1032
1033 typedef struct {
1034         smb_ucs2_t lower;
1035         smb_ucs2_t upper;
1036         unsigned char flags;
1037 } smb_unicode_table_t;
1038
1039 #define TABLE1_BOUNDARY 9450
1040 #define TABLE2_BOUNDARY 64256
1041
1042 static smb_unicode_table_t map_table1[] = {
1043 #include "unicode_map_table1.h"
1044 };
1045
1046 static smb_unicode_table_t map_table2[] = {
1047 #include "unicode_map_table2.h"
1048 };
1049
1050 static unsigned char map_table_flags(smb_ucs2_t v)
1051 {
1052         if (v < TABLE1_BOUNDARY) return map_table1[v].flags;
1053         if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].flags;
1054         return 0;
1055 }
1056
1057 static smb_ucs2_t map_table_lower(smb_ucs2_t v)
1058 {
1059         if (v < TABLE1_BOUNDARY) return map_table1[v].lower;
1060         if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].lower;
1061         return v;
1062 }
1063
1064 static smb_ucs2_t map_table_upper(smb_ucs2_t v)
1065 {
1066         if (v < TABLE1_BOUNDARY) return map_table1[v].upper;
1067         if (v >= TABLE2_BOUNDARY) return map_table2[v - TABLE2_BOUNDARY].upper;
1068         return v;
1069 }
1070
1071 /*******************************************************************
1072  Is an upper case wchar.
1073 ********************************************************************/
1074
1075 int isupper_w( smb_ucs2_t val)
1076 {
1077         return (map_table_flags(val) & UNI_UPPER);
1078 }
1079
1080 /*******************************************************************
1081  Is a lower case wchar.
1082 ********************************************************************/
1083
1084 int islower_w( smb_ucs2_t val)
1085 {
1086         return (map_table_flags(val) & UNI_LOWER);
1087 }
1088
1089 /*******************************************************************
1090  Is a digit wchar.
1091 ********************************************************************/
1092
1093 int isdigit_w( smb_ucs2_t val)
1094 {
1095         return (map_table_flags(val) & UNI_DIGIT);
1096 }
1097
1098 /*******************************************************************
1099  Is a hex digit wchar.
1100 ********************************************************************/
1101
1102 int isxdigit_w( smb_ucs2_t val)
1103 {
1104         return (map_table_flags(val) & UNI_XDIGIT);
1105 }
1106
1107 /*******************************************************************
1108  Is a space wchar.
1109 ********************************************************************/
1110
1111 int isspace_w( smb_ucs2_t val)
1112 {
1113         return (map_table_flags(val) & UNI_SPACE);
1114 }
1115
1116 /*******************************************************************
1117  Convert a wchar to upper case.
1118 ********************************************************************/
1119
1120 smb_ucs2_t toupper_w( smb_ucs2_t val )
1121 {
1122         return map_table_upper(val);
1123 }
1124
1125 /*******************************************************************
1126  Convert a wchar to lower case.
1127 ********************************************************************/
1128
1129 smb_ucs2_t tolower_w( smb_ucs2_t val )
1130 {
1131         return map_table_lower(val);
1132 }
1133
1134 static smb_ucs2_t *last_ptr = NULL;
1135
1136 void set_first_token_w(smb_ucs2_t *ptr)
1137 {
1138         last_ptr = ptr;
1139 }
1140
1141 /****************************************************************************
1142  Get the next token from a string, return False if none found
1143  handles double-quotes. 
1144  Based on a routine by GJC@VILLAGE.COM. 
1145  Extensively modified by Andrew.Tridgell@anu.edu.au
1146  bufsize is in bytes.
1147 ****************************************************************************/
1148
1149 static smb_ucs2_t sep_list[] = { (smb_ucs2_t)' ', (smb_ucs2_t)'\t',  (smb_ucs2_t)'\n',  (smb_ucs2_t)'\r', 0};
1150 static smb_ucs2_t quotechar = (smb_ucs2_t)'\"';
1151
1152 BOOL next_token_w(smb_ucs2_t **ptr, smb_ucs2_t *buff, smb_ucs2_t *sep, size_t bufsize)
1153 {
1154         smb_ucs2_t *s;
1155         BOOL quoted;
1156         size_t len=1;
1157
1158         /*
1159          * Convert bufsize to smb_ucs2_t units.
1160          */
1161
1162         bufsize /= sizeof(smb_ucs2_t);
1163
1164         if (!ptr)
1165                 ptr = &last_ptr;
1166         if (!ptr)
1167                 return(False);
1168
1169         s = *ptr;
1170
1171         /*
1172          * Default to simple separators.
1173          */
1174
1175         if (!sep)
1176                 sep = sep_list;
1177
1178         /*
1179          * Find the first non sep char.
1180          */
1181
1182         while(*s && strchr_w(sep,*s))
1183                 s++;
1184
1185         /*
1186          * Nothing left ?
1187          */
1188
1189         if (!*s)
1190                 return(False);
1191
1192         /*
1193          * Copy over the token.
1194          */
1195
1196         for (quoted = False; len < bufsize && *s && (quoted || !strchr_w(sep,*s)); s++) {
1197                 if (*s == quotechar) {
1198                         quoted = !quoted;
1199                 } else {
1200                         len++;
1201                         *buff++ = *s;
1202                 }
1203         }
1204
1205         *ptr = (*s) ? s+1 : s;  
1206         *buff = 0;
1207         last_ptr = *ptr;
1208
1209         return(True);
1210 }
1211
1212 /****************************************************************************
1213  Convert list of tokens to array; dependent on above routine.
1214  Uses last_ptr from above - bit of a hack.
1215 ****************************************************************************/
1216
1217 smb_ucs2_t **toktocliplist_w(int *ctok, smb_ucs2_t *sep)
1218 {
1219         smb_ucs2_t *s=last_ptr;
1220         int ictok=0;
1221         smb_ucs2_t **ret, **iret;
1222
1223         if (!sep)
1224                 sep = sep_list;
1225
1226         while(*s && strchr_w(sep,*s))
1227                 s++;
1228
1229         /*
1230          * Nothing left ?
1231          */
1232
1233         if (!*s)
1234                 return(NULL);
1235
1236         do {
1237                 ictok++;
1238                 while(*s && (!strchr_w(sep,*s)))
1239                         s++;
1240                 while(*s && strchr_w(sep,*s))
1241                         *s++=0;
1242         } while(*s);
1243
1244         *ctok = ictok;
1245         s = last_ptr;
1246
1247         if (!(ret=iret=malloc(ictok*sizeof(smb_ucs2_t *))))
1248                 return NULL;
1249   
1250         while(ictok--) {
1251                 *iret++=s;
1252                 while(*s++)
1253                         ;
1254                 while(!*s)
1255                         s++;
1256         }
1257
1258         return ret;
1259 }
1260
1261 /*******************************************************************
1262  Case insensitive string compararison.
1263 ********************************************************************/
1264
1265 int StrCaseCmp_w(const smb_ucs2_t *s, const smb_ucs2_t *t)
1266 {
1267         /* 
1268          * Compare until we run out of string, either t or s, or find a difference.
1269          */
1270
1271         while (*s && *t && toupper_w(*s) == toupper_w(*t)) {
1272                 s++;
1273                 t++;
1274         }
1275
1276         return(toupper_w(*s) - toupper_w(*t));
1277 }
1278
1279 /*******************************************************************
1280  Case insensitive string compararison, length limited.
1281  n is in ucs2 units.
1282 ********************************************************************/
1283
1284 int StrnCaseCmp_w(const smb_ucs2_t *s, const smb_ucs2_t *t, size_t n)
1285 {
1286         /*
1287          * Compare until we run out of string, either t or s, or chars.
1288          */
1289
1290         while (n && *s && *t && toupper_w(*s) == toupper_w(*t)) {
1291                 s++;
1292                 t++;
1293                 n--;
1294         }
1295
1296     /*
1297          * Not run out of chars - strings are different lengths.
1298          */
1299
1300     if (n) 
1301       return(toupper_w(*s) - toupper_w(*t));
1302
1303     /*
1304          * Identical up to where we run out of chars, 
1305          * and strings are same length.
1306          */
1307
1308         return(0);
1309 }
1310
1311 /*******************************************************************
1312  Compare 2 strings.
1313 ********************************************************************/
1314
1315 BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
1316 {
1317         if (s1 == s2)
1318                 return(True);
1319         if (!s1 || !s2)
1320                 return(False);
1321   
1322         return(StrCaseCmp_w(s1,s2)==0);
1323 }
1324
1325 /*******************************************************************
1326  Compare 2 strings up to and including the nth char. n is in ucs2
1327  units.
1328 ******************************************************************/
1329
1330 BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
1331 {
1332         if (s1 == s2)
1333                 return(True);
1334         if (!s1 || !s2 || !n)
1335                 return(False);
1336   
1337         return(StrnCaseCmp_w(s1,s2,n)==0);
1338 }
1339
1340 /*******************************************************************
1341  Compare 2 strings (case sensitive).
1342 ********************************************************************/
1343
1344 BOOL strcsequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2)
1345 {
1346         if (s1 == s2)
1347                 return(True);
1348         if (!s1 || !s2)
1349                 return(False);
1350   
1351         return(strcmp_w(s1,s2)==0);
1352 }
1353
1354 /*******************************************************************
1355  Convert a string to lower case.
1356 ********************************************************************/
1357
1358 void strlower_w(smb_ucs2_t *s)
1359 {
1360         while (*s) {
1361                 if (isupper_w(*s))
1362                         *s = tolower_w(*s);
1363                 s++;
1364         }
1365 }
1366
1367 /*******************************************************************
1368  Convert a string to upper case.
1369 ********************************************************************/
1370
1371 void strupper_w(smb_ucs2_t *s)
1372 {
1373         while (*s) {
1374                 if (islower_w(*s))
1375                         *s = toupper_w(*s);
1376                 s++;
1377         }
1378 }
1379
1380 /*******************************************************************
1381  Convert a string to "normal" form.
1382 ********************************************************************/
1383
1384 void strnorm_w(smb_ucs2_t *s)
1385 {
1386         extern int case_default;
1387         if (case_default == CASE_UPPER)
1388                 strupper_w(s);
1389         else
1390                 strlower_w(s);
1391 }
1392
1393 /*******************************************************************
1394  Check if a string is in "normal" case.
1395 ********************************************************************/
1396
1397 BOOL strisnormal_w(smb_ucs2_t *s)
1398 {
1399         extern int case_default;
1400         if (case_default == CASE_UPPER)
1401                 return(!strhaslower_w(s));
1402
1403         return(!strhasupper_w(s));
1404 }
1405
1406 /****************************************************************************
1407  String replace.
1408 ****************************************************************************/
1409
1410 void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc)
1411 {
1412         while (*s) {
1413                 if (oldc == *s)
1414                         *s = newc;
1415                 s++;
1416         }
1417 }
1418
1419 /*******************************************************************
1420  Skip past some strings in a buffer. n is in bytes.
1421 ********************************************************************/
1422
1423 smb_ucs2_t *skip_string_w(smb_ucs2_t *buf,size_t n)
1424 {
1425         while (n--)
1426                 buf += (strlen_w(buf)*sizeof(smb_ucs2_t)) + 1;
1427         return(buf);
1428 }
1429
1430 /*******************************************************************
1431  Count the number of characters in a string. Same as strlen_w in
1432  smb_ucs2_t string units.
1433 ********************************************************************/
1434
1435 size_t str_charnum_w(const smb_ucs2_t *s)
1436 {
1437         return strlen_w(s);
1438 }
1439
1440 /*******************************************************************
1441  Trim the specified elements off the front and back of a string.
1442 ********************************************************************/
1443
1444 BOOL trim_string_w(smb_ucs2_t *s,const smb_ucs2_t *front,const smb_ucs2_t *back)
1445 {
1446         BOOL ret = False;
1447         size_t front_len = (front && *front) ? strlen_w(front) : 0;
1448         size_t back_len = (back && *back) ? strlen_w(back) : 0;
1449         size_t s_len;
1450
1451         while (front_len && strncmp_w(s, front, front_len) == 0) {
1452                 smb_ucs2_t *p = s;
1453                 ret = True;
1454
1455                 while (1) {
1456                         if (!(*p = p[front_len]))
1457                                 break;
1458                         p++;
1459                 }
1460         }
1461
1462         if(back_len) {
1463                 s_len = strlen_w(s);
1464                 while ((s_len >= back_len) && 
1465                         (strncmp_w(s + s_len - back_len, back, back_len)==0)) {
1466                         ret = True;
1467                         s[s_len - back_len] = 0;
1468                         s_len = strlen_w(s);
1469                 }
1470         }
1471
1472         return(ret);
1473 }
1474
1475 /****************************************************************************
1476  Does a string have any uppercase chars in it ?
1477 ****************************************************************************/
1478
1479 BOOL strhasupper_w(const smb_ucs2_t *s)
1480 {
1481         while (*s) {
1482                 if (isupper_w(*s))
1483                         return(True);
1484                 s++;
1485         }
1486         return(False);
1487 }
1488
1489 /****************************************************************************
1490  Does a string have any lowercase chars in it ?
1491 ****************************************************************************/
1492
1493 BOOL strhaslower_w(const smb_ucs2_t *s)
1494 {
1495         while (*s) {
1496                 if (islower(*s))
1497                         return(True);
1498                 s++;
1499         }
1500         return(False);
1501 }
1502
1503 /****************************************************************************
1504  Find the number of 'c' chars in a string.
1505 ****************************************************************************/
1506
1507 size_t count_chars_w(const smb_ucs2_t *s,smb_ucs2_t c)
1508 {
1509         size_t count=0;
1510
1511         while (*s) {
1512                 if (*s == c)
1513                         count++;
1514                 s++;
1515         }
1516         return(count);
1517 }
1518
1519 /*******************************************************************
1520  Return True if a string consists only of one particular character.
1521 ********************************************************************/
1522
1523 BOOL str_is_all_w(const smb_ucs2_t *s,smb_ucs2_t c)
1524 {
1525         if(s == NULL)
1526                 return False;
1527         if(!*s)
1528                 return False;
1529
1530         while (*s) {
1531                 if (*s != c)
1532                         return False;
1533                 s++;
1534         }
1535         return True;
1536 }
1537
1538 /*******************************************************************
1539  Paranoid strcpy into a buffer of given length (includes terminating
1540  zero. Strips out all but 'a-Z0-9' and replaces with '_'. Deliberately
1541  does *NOT* check for multibyte characters. Don't change it !
1542  maxlength is in ucs2 units.
1543 ********************************************************************/
1544
1545 smb_ucs2_t *alpha_strcpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxlength)
1546 {
1547         size_t len, i;
1548
1549         if (!dest) {
1550                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy_w\n"));
1551                 return NULL;
1552         }
1553
1554         if (!src) {
1555                 *dest = 0;
1556                 return dest;
1557         }  
1558
1559         len = strlen_w(src);
1560         if (len >= maxlength)
1561                 len = maxlength - 1;
1562
1563         for(i = 0; i < len; i++) {
1564                 smb_ucs2_t val = src[i];
1565                 if(isupper_w(val) ||islower_w(val) || isdigit_w(val))
1566                         dest[i] = src[i];
1567                 else
1568                         dest[i] = (smb_ucs2_t)'_';
1569         }
1570
1571         dest[i] = 0;
1572
1573         return dest;
1574 }
1575
1576 /****************************************************************************
1577  Like strncpy but always null terminates. Make sure there is room !
1578  The variable n should always be one less than the available size and is in
1579  ucs2 units.
1580 ****************************************************************************/
1581
1582 smb_ucs2_t *StrnCpy_w(smb_ucs2_t *dest,const smb_ucs2_t *src,size_t n)
1583 {
1584         smb_ucs2_t *d = dest;
1585         if (!dest)
1586                 return(NULL);
1587         if (!src) {
1588                 *dest = 0;
1589                 return(dest);
1590         }
1591
1592         while (n-- && (*d++ = *src++))
1593                 ;
1594         *d = 0;
1595         return(dest);
1596 }
1597
1598 /****************************************************************************
1599  Like strncpy but copies up to the character marker. Always null terminates.
1600  returns a pointer to the character marker in the source string (src).
1601  n is in ucs2 units.
1602 ****************************************************************************/
1603
1604 smb_ucs2_t *strncpyn_w(smb_ucs2_t *dest, const smb_ucs2_t *src,size_t n, smb_ucs2_t c)
1605 {
1606         smb_ucs2_t *p;
1607         size_t str_len;
1608
1609         p = strchr_w(src, c);
1610         if (p == NULL) {
1611                 fstring cval;
1612                 smb_ucs2_t mbcval[2];
1613                 mbcval[0] = c;
1614                 mbcval[1] = 0;
1615                 DEBUG(5, ("strncpyn_w: separator character (%s) not found\n",
1616                         unicode_to_unix(cval,mbcval,sizeof(cval)) ));
1617                 return NULL;
1618         }
1619
1620         str_len = PTR_DIFF(p, src) + 1;
1621         safe_strcpy_w(dest, src, MIN(n, str_len));
1622
1623         return p;
1624 }
1625
1626 /*************************************************************
1627  Routine to get hex characters and turn them into a 16 byte array.
1628  The array can be variable length, and any non-hex-numeric
1629  characters are skipped.  "0xnn" or "0Xnn" is specially catered
1630  for. len is in bytes.
1631  Valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
1632 **************************************************************/
1633
1634 static smb_ucs2_t hexprefix[] = { (smb_ucs2_t)'0', (smb_ucs2_t)'x', 0 };
1635 static smb_ucs2_t hexchars[] = { (smb_ucs2_t)'0', (smb_ucs2_t)'1', (smb_ucs2_t)'2', (smb_ucs2_t)'3',
1636                                                                 (smb_ucs2_t)'4', (smb_ucs2_t)'5', (smb_ucs2_t)'6', (smb_ucs2_t)'7',
1637                                                                 (smb_ucs2_t)'8', (smb_ucs2_t)'9', (smb_ucs2_t)'A', (smb_ucs2_t)'B',
1638                                                                 (smb_ucs2_t)'C', (smb_ucs2_t)'D', (smb_ucs2_t)'E', (smb_ucs2_t)'F', 0 };
1639
1640 size_t strhex_to_str_w(char *p, size_t len, const smb_ucs2_t *strhex)
1641 {
1642         size_t i;
1643         size_t num_chars = 0;
1644         unsigned char   lonybble, hinybble;
1645         smb_ucs2_t *p1 = NULL, *p2 = NULL;
1646
1647         /*
1648          * Convert to smb_ucs2_t units.
1649          */
1650
1651         len /= sizeof(smb_ucs2_t);
1652
1653         for (i = 0; i < len && strhex[i] != 0; i++) {
1654                 if (strnequal_w(hexchars, hexprefix, 2)) {
1655                         i++; /* skip two chars */
1656                         continue;
1657                 }
1658
1659                 if (!(p1 = strchr_w(hexchars, toupper_w(strhex[i]))))
1660                         break;
1661
1662                 i++; /* next hex digit */
1663
1664                 if (!(p2 = strchr_w(hexchars, toupper_w(strhex[i]))))
1665                         break;
1666
1667                 /* get the two nybbles */
1668                 hinybble = (PTR_DIFF(p1, hexchars)/sizeof(smb_ucs2_t));
1669                 lonybble = (PTR_DIFF(p2, hexchars)/sizeof(smb_ucs2_t));
1670
1671                 p[num_chars] = (hinybble << 4) | lonybble;
1672                 num_chars++;
1673
1674                 p1 = NULL;
1675                 p2 = NULL;
1676         }
1677         return num_chars;
1678 }
1679
1680 /****************************************************************************
1681  Check if a string is part of a list.
1682 ****************************************************************************/
1683
1684 BOOL in_list_w(smb_ucs2_t *s,smb_ucs2_t *list,BOOL casesensitive)
1685 {
1686         wpstring tok;
1687         smb_ucs2_t *p=list;
1688
1689         if (!list)
1690                 return(False);
1691
1692         while (next_token_w(&p,tok,LIST_SEP_W,sizeof(tok))) {
1693                 if (casesensitive) {
1694                         if (strcmp_w(tok,s) == 0)
1695                                 return(True);
1696                 } else {
1697                         if (StrCaseCmp_w(tok,s) == 0)
1698                                 return(True);
1699                 }
1700         }
1701         return(False);
1702 }
1703
1704 /* This is used to prevent lots of mallocs of size 2 */
1705 static smb_ucs2_t *null_string = NULL;
1706
1707 /****************************************************************************
1708  Set a string value, allocing the space for the string.
1709 ****************************************************************************/
1710
1711 BOOL string_init_w(smb_ucs2_t **dest,const smb_ucs2_t *src)
1712 {
1713         size_t l;
1714
1715         if (!null_string) {
1716                 if((null_string = (smb_ucs2_t *)malloc(sizeof(smb_ucs2_t))) == NULL) {
1717                         DEBUG(0,("string_init_w: malloc fail for null_string.\n"));
1718                 return False;
1719                 }
1720                 *null_string = 0;
1721         }
1722
1723         if (!src)     
1724                 src = null_string;
1725
1726         l = strlen_w(src);
1727
1728         if (l == 0)
1729                 *dest = null_string;
1730         else {
1731                 (*dest) = (smb_ucs2_t *)malloc(sizeof(smb_ucs2_t)*(l+1));
1732                 if ((*dest) == NULL) {
1733                         DEBUG(0,("Out of memory in string_init_w\n"));
1734                         return False;
1735                 }
1736
1737                 wpstrcpy(*dest,src);
1738         }
1739         return(True);
1740 }
1741
1742 /****************************************************************************
1743  Free a string value.
1744 ****************************************************************************/
1745
1746 void string_free_w(smb_ucs2_t **s)
1747 {
1748         if (!s || !(*s))
1749                 return;
1750         if (*s == null_string)
1751                 *s = NULL;
1752         if (*s)
1753                 free((char *)*s);
1754         *s = NULL;
1755 }
1756
1757 /****************************************************************************
1758  Set a string value, allocing the space for the string, and deallocating any 
1759  existing space.
1760 ****************************************************************************/
1761
1762 BOOL string_set_w(smb_ucs2_t **dest,const smb_ucs2_t *src)
1763 {
1764         string_free_w(dest);
1765
1766         return(string_init_w(dest,src));
1767 }
1768
1769 /****************************************************************************
1770  Substitute a string for a pattern in another string. Make sure there is 
1771  enough room !
1772
1773  This routine looks for pattern in s and replaces it with 
1774  insert. It may do multiple replacements.
1775
1776  Any of " ; ' $ or ` in the insert string are replaced with _
1777  if len==0 then no length check is performed
1778  len is in ucs2 units.
1779 ****************************************************************************/
1780
1781 void string_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert, size_t len)
1782 {
1783         smb_ucs2_t *p;
1784         ssize_t ls,lp,li, i;
1785
1786         if (!insert || !pattern || !s)
1787                 return;
1788
1789         ls = (ssize_t)strlen_w(s);
1790         lp = (ssize_t)strlen_w(pattern);
1791         li = (ssize_t)strlen_w(insert);
1792
1793         if (!*pattern)
1794                 return;
1795         
1796         while (lp <= ls && (p = strstr_w(s,pattern))) {
1797                 if (len && (ls + (li-lp) >= len)) {
1798                         fstring out;
1799                         DEBUG(0,("ERROR: string overflow by %d in string_sub_w(%.50s, %d)\n", 
1800                                  (int)(sizeof(smb_ucs2_t)*(ls + (li-lp) - len)),
1801                                  unicode_to_unix(out,pattern,sizeof(out)), (int)len*sizeof(smb_ucs2_t)));
1802                         break;
1803                 }
1804                 if (li != lp)
1805                         memmove(p+li,p+lp,sizeof(smb_ucs2_t)*(strlen_w(p+lp)+1));
1806
1807                 for (i=0;i<li;i++) {
1808                         switch (insert[i]) {
1809                         case (smb_ucs2_t)'`':
1810                         case (smb_ucs2_t)'"':
1811                         case (smb_ucs2_t)'\'':
1812                         case (smb_ucs2_t)';':
1813                         case (smb_ucs2_t)'$':
1814                         case (smb_ucs2_t)'%':
1815                         case (smb_ucs2_t)'\r':
1816                         case (smb_ucs2_t)'\n':
1817                                 p[i] = (smb_ucs2_t)'_';
1818                                 break;
1819                         default:
1820                                 p[i] = insert[i];
1821                         }
1822                 }
1823                 s = p + li;
1824                 ls += (li-lp);
1825         }
1826 }
1827
1828 void fstring_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert)
1829 {
1830         string_sub_w(s, pattern, insert, sizeof(wfstring));
1831 }
1832
1833 void pstring_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,smb_ucs2_t *insert)
1834 {
1835         string_sub_w(s, pattern, insert, sizeof(wpstring));
1836 }
1837
1838 /****************************************************************************
1839  Similar to string_sub() but allows for any character to be substituted. 
1840  Use with caution !
1841  if len==0 then no length check is performed.
1842 ****************************************************************************/
1843
1844 void all_string_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert, size_t len)
1845 {
1846         smb_ucs2_t *p;
1847         ssize_t ls,lp,li;
1848
1849         if (!insert || !pattern || !s)
1850                 return;
1851
1852         ls = (ssize_t)strlen_w(s);
1853         lp = (ssize_t)strlen_w(pattern);
1854         li = (ssize_t)strlen_w(insert);
1855
1856         if (!*pattern)
1857                 return;
1858         
1859         while (lp <= ls && (p = strstr_w(s,pattern))) {
1860                 if (len && (ls + (li-lp) >= len)) {
1861                         fstring out;
1862                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub_w(%.50s, %d)\n", 
1863                                  (int)(sizeof(smb_ucs2_t)*(ls + (li-lp) - len)),
1864                                  unicode_to_unix(out,pattern,sizeof(out)), (int)len*sizeof(smb_ucs2_t)));
1865                         break;
1866                 }
1867                 if (li != lp)
1868                         memmove(p+li,p+lp,sizeof(smb_ucs2_t)*(strlen_w(p+lp)+1));
1869
1870                 memcpy(p, insert, li*sizeof(smb_ucs2_t));
1871                 s = p + li;
1872                 ls += (li-lp);
1873         }
1874 }
1875
1876 /****************************************************************************
1877  Splits out the front and back at a separator.
1878 ****************************************************************************/
1879
1880 void split_at_last_component_w(smb_ucs2_t *path, smb_ucs2_t *front, smb_ucs2_t sep, smb_ucs2_t *back)
1881 {
1882     smb_ucs2_t *p = strrchr_w(path, sep);
1883
1884         if (p != NULL)
1885                 *p = 0;
1886
1887         if (front != NULL)
1888                 wpstrcpy(front, path);
1889
1890         if (p != NULL) {
1891                 if (back != NULL)
1892                         wpstrcpy(back, p+1);
1893                 *p = (smb_ucs2_t)'\\';
1894         } else {
1895                 if (back != NULL)
1896                         back[0] = 0;
1897         }
1898 }
1899
1900
1901 /****************************************************************************
1902  Write an octal as a string.
1903 ****************************************************************************/
1904
1905 smb_ucs2_t *octal_string_w(int i)
1906 {
1907         static smb_ucs2_t wret[64];
1908         char ret[64];
1909
1910         if (i == -1)
1911                 slprintf(ret, sizeof(ret), "-1");
1912         else 
1913                 slprintf(ret, sizeof(ret), "0%o", i);
1914         return unix_to_unicode(wret, ret, sizeof(wret));
1915 }
1916
1917
1918 /****************************************************************************
1919  Truncate a string at a specified length.
1920  length is in ucs2 units.
1921 ****************************************************************************/
1922
1923 smb_ucs2_t *string_truncate_w(smb_ucs2_t *s, size_t length)
1924 {
1925         if (s && strlen_w(s) > length)
1926                 s[length] = 0;
1927
1928         return s;
1929 }