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