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