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