preparing for release of alpha.2.5
[Samba.git] / source / lib / util_wunistr.c
blob0974bad29241a87677721422abd963ddbecb6d42
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
22 #include "includes.h"
24 extern int DEBUGLEVEL;
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 };
30 * The following are the codepage to ucs2 and vica versa maps.
31 * These are dynamically loaded from a unicode translation file.
34 static smb_ucs2_t *doscp_to_ucs2;
35 static uint16 *ucs2_to_doscp;
37 static smb_ucs2_t *unixcp_to_ucs2;
38 static uint16 *ucs2_to_unixcp;
40 /*******************************************************************
41 Write a string in (little-endian) unicode format. src is in
42 the current DOS codepage. len is the length in bytes of the
43 string pointed to by dst.
45 if null_terminate is True then null terminate the packet (adds 2 bytes)
47 the return value is the length consumed by the string, including the
48 null termination if applied
49 ********************************************************************/
51 int dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
53 int ret = 0;
54 while (*src && (len > 2)) {
55 size_t skip = get_character_len(*src);
56 smb_ucs2_t val = (*src & 0xff);
59 * If this is a multibyte character (and all DOS/Windows
60 * codepages have at maximum 2 byte multibyte characters)
61 * then work out the index value for the unicode conversion.
64 if (skip == 2)
65 val = ((val << 8) | (src[1] & 0xff));
67 SSVAL(dst,ret,doscp_to_ucs2[val]);
68 ret += 2;
69 len -= 2;
70 if (skip)
71 src += skip;
72 else
73 src++;
75 if (null_terminate) {
76 SSVAL(dst,ret,0);
77 ret += 2;
79 return(ret);
82 #ifndef MAXUNI
83 #define MAXUNI 1024
84 #endif
86 /*******************************************************************
87 Return a DOS codepage version of a little-endian unicode string.
88 len is the filename length (ignoring any terminating zero) in uin16
89 units. Always null terminates.
90 Hack alert: uses fixed buffer(s).
91 ********************************************************************/
93 char *dos_unistrn2(uint16 *src, int len)
95 static char lbufs[8][MAXUNI];
96 static int nexti;
97 char *lbuf = lbufs[nexti];
98 char *p;
100 nexti = (nexti+1)%8;
102 for (p = lbuf; (len > 0) && (p-lbuf < MAXUNI-3) && *src; len--, src++) {
103 uint16 ucs2_val = SVAL(src,0);
104 uint16 cp_val = ucs2_to_doscp[ucs2_val];
106 if (cp_val < 256)
107 *p++ = (char)cp_val;
108 else {
109 *p++ = (cp_val >> 8) & 0xff;
110 *p++ = (cp_val & 0xff);
114 *p = 0;
115 return lbuf;
118 static char lbufs[8][MAXUNI];
119 static int nexti;
121 /*******************************************************************
122 Return a DOS codepage version of a little-endian unicode string.
123 Hack alert: uses fixed buffer(s).
124 ********************************************************************/
126 char *dos_unistr2(uint16 *src)
128 char *lbuf = lbufs[nexti];
129 char *p;
131 nexti = (nexti+1)%8;
133 for (p = lbuf; *src && (p-lbuf < MAXUNI-3); src++) {
134 uint16 ucs2_val = SVAL(src,0);
135 uint16 cp_val = ucs2_to_doscp[ucs2_val];
137 if (cp_val < 256)
138 *p++ = (char)cp_val;
139 else {
140 *p++ = (cp_val >> 8) & 0xff;
141 *p++ = (cp_val & 0xff);
145 *p = 0;
146 return lbuf;
149 /*******************************************************************
150 Return a DOS codepage version of a little-endian unicode string
151 ********************************************************************/
153 char *dos_unistr2_to_str(UNISTR2 *str)
155 char *lbuf = lbufs[nexti];
156 char *p;
157 uint16 *src = str->buffer;
158 int max_size = MIN(sizeof(str->buffer)-3, str->uni_str_len);
160 nexti = (nexti+1)%8;
162 for (p = lbuf; *src && p-lbuf < max_size; src++) {
163 uint16 ucs2_val = SVAL(src,0);
164 uint16 cp_val = ucs2_to_doscp[ucs2_val];
166 if (cp_val < 256)
167 *p++ = (char)cp_val;
168 else {
169 *p++ = (cp_val >> 8) & 0xff;
170 *p++ = (cp_val & 0xff);
174 *p = 0;
175 return lbuf;
178 /*******************************************************************
179 Convert a UNISTR2 structure to an ASCII string
180 Warning: this version does DOS codepage.
181 ********************************************************************/
182 #if 0
183 void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
185 char *destend;
186 const uint16 *src;
187 size_t len;
188 register uint16 c;
190 src = str->buffer;
191 len = MIN(str->uni_str_len, maxlen);
192 destend = dest + len;
194 while (dest < destend)
196 uint16 ucs2_val;
197 uint16 cp_val;
199 c = *src;
200 if (c == 0)
202 break;
205 ucs2_val = SVAL(src++,0);
206 cp_val = ucs2_to_doscp[ucs2_val];
208 if (cp_val < 256)
209 *(dest++) = (char)cp_val;
210 else {
211 *dest= (cp_val >> 8) & 0xff;
212 *(dest++) = (cp_val & 0xff);
216 *dest = 0;
218 #endif
219 /*******************************************************************
220 Return a DOS codepage version of a NOTunicode string
221 ********************************************************************/
223 char *dos_buffer2_to_str(BUFFER2 *str)
225 char *lbuf = lbufs[nexti];
226 char *p;
227 uint16 *src = str->buffer;
228 int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
230 nexti = (nexti+1)%8;
232 for (p = lbuf; *src && p-lbuf < max_size; src++) {
233 uint16 ucs2_val = SVAL(src,0);
234 uint16 cp_val = ucs2_to_doscp[ucs2_val];
236 if (cp_val < 256)
237 *p++ = (char)cp_val;
238 else {
239 *p++ = (cp_val >> 8) & 0xff;
240 *p++ = (cp_val & 0xff);
244 *p = 0;
245 return lbuf;
248 /*******************************************************************
249 Return a dos codepage version of a NOTunicode string
250 ********************************************************************/
252 char *dos_buffer2_to_multistr(BUFFER2 *str)
254 char *lbuf = lbufs[nexti];
255 char *p;
256 uint16 *src = str->buffer;
257 int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
259 nexti = (nexti+1)%8;
261 for (p = lbuf; p-lbuf < max_size; src++) {
262 if (*src == 0) {
263 *p++ = ' ';
264 } else {
265 uint16 ucs2_val = SVAL(src,0);
266 uint16 cp_val = ucs2_to_doscp[ucs2_val];
268 if (cp_val < 256)
269 *p++ = (char)cp_val;
270 else {
271 *p++ = (cp_val >> 8) & 0xff;
272 *p++ = (cp_val & 0xff);
277 *p = 0;
278 return lbuf;
281 /*******************************************************************
282 Create a null-terminated unicode string from a null-terminated DOS
283 codepage string.
284 Return number of unicode chars copied, excluding the null character.
285 Unicode strings created are in little-endian format.
286 ********************************************************************/
288 size_t dos_struni2(char *dst, const char *src, size_t max_len)
290 size_t len = 0;
292 if (dst == NULL)
293 return 0;
295 if (src != NULL) {
296 for (; *src && len < max_len-2; len++, dst +=2) {
297 size_t skip = get_character_len(*src);
298 smb_ucs2_t val = (*src & 0xff);
301 * If this is a multibyte character (and all DOS/Windows
302 * codepages have at maximum 2 byte multibyte characters)
303 * then work out the index value for the unicode conversion.
306 if (skip == 2)
307 val = ((val << 8) | (src[1] & 0xff));
309 SSVAL(dst,0,doscp_to_ucs2[val]);
310 if (skip)
311 src += skip;
312 else
313 src++;
317 SSVAL(dst,0,0);
319 return len;
322 /*******************************************************************
323 Return a DOS codepage version of a little-endian unicode string.
324 Hack alert: uses fixed buffer(s).
325 ********************************************************************/
327 char *dos_unistr(char *buf)
329 char *lbuf = lbufs[nexti];
330 uint16 *src = (uint16 *)buf;
331 char *p;
333 nexti = (nexti+1)%8;
335 for (p = lbuf; *src && p-lbuf < MAXUNI-3; src++) {
336 uint16 ucs2_val = SVAL(src,0);
337 uint16 cp_val = ucs2_to_doscp[ucs2_val];
339 if (cp_val < 256)
340 *p++ = (char)cp_val;
341 else {
342 *p++ = (cp_val >> 8) & 0xff;
343 *p++ = (cp_val & 0xff);
347 *p = 0;
348 return lbuf;
351 /*******************************************************************
352 Free any existing maps.
353 ********************************************************************/
355 static void free_maps(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
357 /* this handles identity mappings where we share the pointer */
358 if (*pp_ucs2_to_cp == *pp_cp_to_ucs2) {
359 *pp_ucs2_to_cp = NULL;
362 if (*pp_cp_to_ucs2) {
363 free(*pp_cp_to_ucs2);
364 *pp_cp_to_ucs2 = NULL;
367 if (*pp_ucs2_to_cp) {
368 free(*pp_ucs2_to_cp);
369 *pp_ucs2_to_cp = NULL;
374 /*******************************************************************
375 Build a default (null) codepage to unicode map.
376 ********************************************************************/
378 void default_unicode_map(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
380 int i;
382 free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
384 if ((*pp_ucs2_to_cp = (uint16 *)malloc(2*65536)) == NULL) {
385 DEBUG(0,("default_unicode_map: malloc fail for ucs2_to_cp size %u.\n", 2*65536));
386 abort();
389 *pp_cp_to_ucs2 = *pp_ucs2_to_cp; /* Default map is an identity. */
390 for (i = 0; i < 65536; i++)
391 (*pp_cp_to_ucs2)[i] = i;
394 /*******************************************************************
395 Load a codepage to unicode and vica-versa map.
396 ********************************************************************/
398 BOOL load_unicode_map(const char *codepage, smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
400 pstring unicode_map_file_name;
401 FILE *fp = NULL;
402 SMB_STRUCT_STAT st;
403 smb_ucs2_t *cp_to_ucs2 = *pp_cp_to_ucs2;
404 uint16 *ucs2_to_cp = *pp_ucs2_to_cp;
405 size_t cp_to_ucs2_size;
406 size_t ucs2_to_cp_size;
407 size_t i;
408 size_t size;
409 char buf[UNICODE_MAP_HEADER_SIZE];
411 DEBUG(5, ("load_unicode_map: loading unicode map for codepage %s.\n", codepage));
413 if (*codepage == '\0')
414 goto clean_and_exit;
416 if(strlen(CODEPAGEDIR) + 13 + strlen(codepage) > sizeof(unicode_map_file_name)) {
417 DEBUG(0,("load_unicode_map: filename too long to load\n"));
418 goto clean_and_exit;
421 pstrcpy(unicode_map_file_name, CODEPAGEDIR);
422 pstrcat(unicode_map_file_name, "/");
423 pstrcat(unicode_map_file_name, "unicode_map.");
424 pstrcat(unicode_map_file_name, codepage);
426 if(sys_stat(unicode_map_file_name,&st)!=0) {
427 DEBUG(0,("load_unicode_map: filename %s does not exist.\n",
428 unicode_map_file_name));
429 goto clean_and_exit;
432 size = st.st_size;
434 if ((size != UNICODE_MAP_HEADER_SIZE + 4*65536) && (size != UNICODE_MAP_HEADER_SIZE +(2*256 + 2*65536))) {
435 DEBUG(0,("load_unicode_map: file %s is an incorrect size for a \
436 unicode map file (size=%d).\n", unicode_map_file_name, (int)size));
437 goto clean_and_exit;
440 if((fp = sys_fopen( unicode_map_file_name, "r")) == NULL) {
441 DEBUG(0,("load_unicode_map: cannot open file %s. Error was %s\n",
442 unicode_map_file_name, strerror(errno)));
443 goto clean_and_exit;
446 if(fread( buf, 1, UNICODE_MAP_HEADER_SIZE, fp)!=UNICODE_MAP_HEADER_SIZE) {
447 DEBUG(0,("load_unicode_map: cannot read header from file %s. Error was %s\n",
448 unicode_map_file_name, strerror(errno)));
449 goto clean_and_exit;
452 /* Check the version value */
453 if(SVAL(buf,UNICODE_MAP_VERSION_OFFSET) != UNICODE_MAP_FILE_VERSION_ID) {
454 DEBUG(0,("load_unicode_map: filename %s has incorrect version id. \
455 Needed %hu, got %hu.\n",
456 unicode_map_file_name, (uint16)UNICODE_MAP_FILE_VERSION_ID,
457 SVAL(buf,UNICODE_MAP_VERSION_OFFSET)));
458 goto clean_and_exit;
461 /* Check the codepage value */
462 if(!strequal(&buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], codepage)) {
463 DEBUG(0,("load_unicode_map: codepage %s in file %s is not the same as that \
464 requested (%s).\n", &buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], unicode_map_file_name, codepage ));
465 goto clean_and_exit;
468 ucs2_to_cp_size = 2*65536;
469 if (size == UNICODE_MAP_HEADER_SIZE + 4*65536) {
471 * This is a multibyte code page.
473 cp_to_ucs2_size = 2*65536;
474 } else {
476 * Single byte code page.
478 cp_to_ucs2_size = 2*256;
482 * Free any old translation tables.
485 free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
487 if ((cp_to_ucs2 = (smb_ucs2_t *)malloc(cp_to_ucs2_size)) == NULL) {
488 DEBUG(0,("load_unicode_map: malloc fail for cp_to_ucs2 size %u.\n", cp_to_ucs2_size ));
489 goto clean_and_exit;
492 if ((ucs2_to_cp = (uint16 *)malloc(ucs2_to_cp_size)) == NULL) {
493 DEBUG(0,("load_unicode_map: malloc fail for ucs2_to_cp size %u.\n", ucs2_to_cp_size ));
494 goto clean_and_exit;
497 if(fread( (char *)cp_to_ucs2, 1, cp_to_ucs2_size, fp)!=cp_to_ucs2_size) {
498 DEBUG(0,("load_unicode_map: cannot read cp_to_ucs2 from file %s. Error was %s\n",
499 unicode_map_file_name, strerror(errno)));
500 goto clean_and_exit;
503 if(fread( (char *)ucs2_to_cp, 1, ucs2_to_cp_size, fp)!=ucs2_to_cp_size) {
504 DEBUG(0,("load_unicode_map: cannot read ucs2_to_cp from file %s. Error was %s\n",
505 unicode_map_file_name, strerror(errno)));
506 goto clean_and_exit;
510 * Now ensure the 16 bit values are in the correct endianness.
513 for (i = 0; i < cp_to_ucs2_size/2; i++)
514 cp_to_ucs2[i] = SVAL(cp_to_ucs2,i*2);
516 for (i = 0; i < ucs2_to_cp_size/2; i++)
517 ucs2_to_cp[i] = SVAL(ucs2_to_cp,i*2);
519 fclose(fp);
521 *pp_cp_to_ucs2 = cp_to_ucs2;
522 *pp_ucs2_to_cp = ucs2_to_cp;
524 return True;
526 clean_and_exit:
528 /* pseudo destructor :-) */
530 if(fp != NULL)
531 fclose(fp);
533 free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
535 default_unicode_map(pp_cp_to_ucs2, pp_ucs2_to_cp);
537 return False;
540 /*******************************************************************
541 Load a dos codepage to unicode and vica-versa map.
542 ********************************************************************/
544 BOOL load_dos_unicode_map(int codepage)
546 fstring codepage_str;
548 slprintf(codepage_str, sizeof(fstring)-1, "%03d", codepage);
549 return load_unicode_map(codepage_str, &doscp_to_ucs2, &ucs2_to_doscp);
552 /*******************************************************************
553 Load a UNIX codepage to unicode and vica-versa map.
554 ********************************************************************/
556 BOOL load_unix_unicode_map(const char *unix_char_set)
558 fstring upper_unix_char_set;
560 fstrcpy(upper_unix_char_set, unix_char_set);
561 strupper(upper_unix_char_set);
562 return load_unicode_map(upper_unix_char_set, &unixcp_to_ucs2, &ucs2_to_unixcp);
565 /*******************************************************************
566 The following functions reproduce many of the non-UNICODE standard
567 string functions in Samba.
568 ********************************************************************/
570 /*******************************************************************
571 Convert a UNICODE string to multibyte format. Note that the 'src' is in
572 native byte order, not little endian. Always zero terminates.
573 dst_len is in bytes.
574 ********************************************************************/
576 static char *unicode_to_multibyte(char *dst, const smb_ucs2_t *src,
577 size_t dst_len, const uint16 *ucs2_to_cp)
579 size_t dst_pos;
581 for(dst_pos = 0; *src && (dst_pos < dst_len - 1);) {
582 smb_ucs2_t val = ucs2_to_cp[*src++];
583 if(val < 256) {
584 dst[dst_pos++] = (char)val;
585 } else {
587 if(dst_pos >= dst_len - 2)
588 break;
591 * A 2 byte value is always written as
592 * high/low into the buffer stream.
595 dst[dst_pos++] = (char)((val >> 8) & 0xff);
596 dst[dst_pos++] = (char)(val & 0xff);
600 dst[dst_pos] = '\0';
602 return dst;
605 /*******************************************************************
606 Convert a multibyte string to UNICODE format. Note that the 'dst' is in
607 native byte order, not little endian. Always zero terminates.
608 dst_len is in bytes.
609 ********************************************************************/
611 smb_ucs2_t *multibyte_to_unicode(smb_ucs2_t *dst, const char *src,
612 size_t dst_len, smb_ucs2_t *cp_to_ucs2)
614 size_t i;
616 dst_len /= sizeof(smb_ucs2_t); /* Convert to smb_ucs2_t units. */
618 for(i = 0; (i < (dst_len - 1)) && src[i];) {
619 size_t skip = skip_multibyte_char(*src);
620 smb_ucs2_t val = (*src & 0xff);
623 * If this is a multibyte character
624 * then work out the index value for the unicode conversion.
627 if (skip == 2)
628 val = ((val << 8) | (src[1] & 0xff));
630 dst[i++] = cp_to_ucs2[val];
631 if (skip)
632 src += skip;
633 else
634 src++;
637 dst[i] = 0;
639 return dst;
642 /*******************************************************************
643 Convert a UNICODE string to multibyte format. Note that the 'src' is in
644 native byte order, not little endian. Always zero terminates.
645 This function may be replaced if the MB codepage format is an
646 encoded one (ie. utf8, hex). See the code in lib/kanji.c
647 for details. dst_len is in bytes.
648 ********************************************************************/
650 char *unicode_to_unix(char *dst, const smb_ucs2_t *src, size_t dst_len)
652 return unicode_to_multibyte(dst, src, dst_len, ucs2_to_unixcp);
655 /*******************************************************************
656 Convert a UNIX string to UNICODE format. Note that the 'dst' is in
657 native byte order, not little endian. Always zero terminates.
658 This function may be replaced if the UNIX codepage format is a
659 multi-byte one (ie. JIS, SJIS or utf8). See the code in lib/kanji.c
660 for details. dst_len is in bytes, not ucs2 units.
661 ********************************************************************/
663 smb_ucs2_t *unix_to_unicode(smb_ucs2_t *dst, const char *src, size_t dst_len)
665 return multibyte_to_unicode(dst, src, dst_len, unixcp_to_ucs2);
668 /*******************************************************************
669 Convert a UNICODE string to DOS format. Note that the 'src' is in
670 native byte order, not little endian. Always zero terminates.
671 dst_len is in bytes.
672 ********************************************************************/
674 char *unicode_to_dos(char *dst, const smb_ucs2_t *src, size_t dst_len)
676 return unicode_to_multibyte(dst, src, dst_len, ucs2_to_doscp);
679 /*******************************************************************
680 Convert a DOS string to UNICODE format. Note that the 'dst' is in
681 native byte order, not little endian. Always zero terminates.
682 This function may be replaced if the DOS codepage format is a
683 multi-byte one (ie. JIS, SJIS or utf8). See the code in lib/kanji.c
684 for details. dst_len is in bytes, not ucs2 units.
685 ********************************************************************/
687 smb_ucs2_t *dos_to_unicode(smb_ucs2_t *dst, const char *src, size_t dst_len)
689 return multibyte_to_unicode(dst, src, dst_len, doscp_to_ucs2);
692 /*******************************************************************
693 Count the number of characters in a smb_ucs2_t string.
694 ********************************************************************/
696 size_t strlen_w(const smb_ucs2_t *src)
698 size_t len;
700 for(len = 0; *src; len++)
703 return len;
706 /*******************************************************************
707 Safe wstring copy into a known length string. maxlength includes
708 the terminating zero. maxlength is in ucs2 units.
709 ********************************************************************/
711 smb_ucs2_t *safe_strcpy_w(smb_ucs2_t *dest,const smb_ucs2_t *src, size_t maxlength)
713 size_t ucs2_len;
715 if (!dest) {
716 DEBUG(0,("ERROR: NULL dest in safe_strcpy_w\n"));
717 return NULL;
720 if (!src) {
721 *dest = 0;
722 return dest;
725 maxlength /= sizeof(smb_ucs2_t);
727 ucs2_len = strlen_w(src);
729 if (ucs2_len >= maxlength) {
730 fstring out;
731 DEBUG(0,("ERROR: string overflow by %u bytes in safe_strcpy_w [%.50s]\n",
732 (unsigned int)((ucs2_len-maxlength)*sizeof(smb_ucs2_t)),
733 unicode_to_unix(out,src,sizeof(out))) );
734 ucs2_len = maxlength - 1;
737 memcpy(dest, src, ucs2_len*sizeof(smb_ucs2_t));
738 dest[ucs2_len] = 0;
739 return dest;
742 /*******************************************************************
743 Safe string cat into a string. maxlength includes the terminating zero.
744 maxlength is in ucs2 units.
745 ********************************************************************/
747 smb_ucs2_t *safe_strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxlength)
749 size_t ucs2_src_len, ucs2_dest_len;
751 if (!dest) {
752 DEBUG(0,("ERROR: NULL dest in safe_strcat_w\n"));
753 return NULL;
756 if (!src)
757 return dest;
759 ucs2_src_len = strlen_w(src);
760 ucs2_dest_len = strlen_w(dest);
762 if (ucs2_src_len + ucs2_dest_len >= maxlength) {
763 fstring out;
764 int new_len = maxlength - ucs2_dest_len - 1;
765 DEBUG(0,("ERROR: string overflow by %u characters in safe_strcat_w [%.50s]\n",
766 (unsigned int)(sizeof(smb_ucs2_t)*(ucs2_src_len + ucs2_dest_len - maxlength)),
767 unicode_to_unix(out,src,sizeof(out))) );
768 ucs2_src_len = (size_t)(new_len > 0 ? new_len : 0);
771 memcpy(&dest[ucs2_dest_len], src, ucs2_src_len*sizeof(smb_ucs2_t));
772 dest[ucs2_dest_len + ucs2_src_len] = 0;
773 return dest;
776 /*******************************************************************
777 Compare the two strings s1 and s2.
778 ********************************************************************/
780 int strcmp_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
782 smb_ucs2_t c1, c2;
784 for (;;) {
785 c1 = *s1++;
786 c2 = *s2++;
788 if (c1 != c2)
789 return c1 - c2;
791 if (c1 == 0)
792 return 0;
794 return 0;
797 /*******************************************************************
798 Compare the first n characters of s1 to s2. len is in ucs2 units.
799 ********************************************************************/
801 int strncmp_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2, size_t len)
803 smb_ucs2_t c1, c2;
805 for (; len != 0; --len) {
806 c1 = *s1++;
807 c2 = *s2++;
809 if (c1 != c2)
810 return c1 - c2;
812 if (c1 == 0)
813 return 0;
816 return 0;
819 /*******************************************************************
820 Search string s2 from s1.
821 ********************************************************************/
823 smb_ucs2_t *strstr_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
825 size_t len = strlen_w(s2);
827 if (!*s2)
828 return (smb_ucs2_t *)s1;
830 for(;*s1; s1++) {
831 if (*s1 == *s2) {
832 if (strncmp_w(s1, s2, len) == 0)
833 return (smb_ucs2_t *)s1;
836 return NULL;
839 /*******************************************************************
840 Search for ucs2 char c from the beginning of s.
841 ********************************************************************/
843 smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
845 do {
846 if (*s == c)
847 return (smb_ucs2_t *)s;
848 } while (*s++);
850 return NULL;
853 /*******************************************************************
854 Search for ucs2 char c from the end of s.
855 ********************************************************************/
857 smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
859 smb_ucs2_t *retval = 0;
861 do {
862 if (*s == c)
863 retval = (smb_ucs2_t *)s;
864 } while (*s++);
866 return retval;
869 /*******************************************************************
870 Search token from s1 separated by any ucs2 char of s2.
871 ********************************************************************/
873 smb_ucs2_t *strtok_w(smb_ucs2_t *s1, const smb_ucs2_t *s2)
875 static smb_ucs2_t *s = NULL;
876 smb_ucs2_t *q;
878 if (!s1) {
879 if (!s)
880 return NULL;
881 s1 = s;
884 for (q = s1; *s1; s1++) {
885 smb_ucs2_t *p = strchr_w(s2, *s1);
886 if (p) {
887 if (s1 != q) {
888 s = s1 + 1;
889 *s1 = '\0';
890 return q;
892 q = s1 + 1;
896 s = NULL;
897 if (*q)
898 return q;
900 return NULL;
903 /*******************************************************************
904 Duplicate a ucs2 string.
905 ********************************************************************/
907 smb_ucs2_t *strdup_w(const smb_ucs2_t *s)
909 size_t newlen = (strlen_w(s)+1)*sizeof(smb_ucs2_t);
910 smb_ucs2_t *newstr = (smb_ucs2_t *)malloc(newlen);
911 if (newstr == NULL)
912 return NULL;
913 safe_strcpy_w(newstr, s, newlen);
914 return newstr;
917 /*******************************************************************
918 Mapping tables for UNICODE character. Allows toupper/tolower and
919 isXXX functions to work.
920 ********************************************************************/
922 typedef struct {
923 smb_ucs2_t lower;
924 smb_ucs2_t upper;
925 unsigned char flags;
926 } smb_unicode_table_t;
928 static smb_unicode_table_t map_table[] = {
929 #include "unicode_map_table.h"
932 /*******************************************************************
933 Is an upper case wchar.
934 ********************************************************************/
936 int isupper_w( smb_ucs2_t val)
938 return (map_table[val].flags & UNI_UPPER);
941 /*******************************************************************
942 Is a lower case wchar.
943 ********************************************************************/
945 int islower_w( smb_ucs2_t val)
947 return (map_table[val].flags & UNI_LOWER);
950 /*******************************************************************
951 Is a digit wchar.
952 ********************************************************************/
954 int isdigit_w( smb_ucs2_t val)
956 return (map_table[val].flags & UNI_DIGIT);
959 /*******************************************************************
960 Is a hex digit wchar.
961 ********************************************************************/
963 int isxdigit_w( smb_ucs2_t val)
965 return (map_table[val].flags & UNI_XDIGIT);
968 /*******************************************************************
969 Is a space wchar.
970 ********************************************************************/
972 int isspace_w( smb_ucs2_t val)
974 return (map_table[val].flags & UNI_SPACE);
977 /*******************************************************************
978 Convert a wchar to upper case.
979 ********************************************************************/
981 smb_ucs2_t toupper_w( smb_ucs2_t val )
983 return map_table[val].upper;
986 /*******************************************************************
987 Convert a wchar to lower case.
988 ********************************************************************/
990 smb_ucs2_t tolower_w( smb_ucs2_t val )
992 return map_table[val].lower;
995 static smb_ucs2_t *last_ptr = NULL;
997 void set_first_token_w(smb_ucs2_t *ptr)
999 last_ptr = ptr;
1002 /****************************************************************************
1003 Get the next token from a string, return False if none found
1004 handles double-quotes.
1005 Based on a routine by GJC@VILLAGE.COM.
1006 Extensively modified by Andrew.Tridgell@anu.edu.au
1007 bufsize is in bytes.
1008 ****************************************************************************/
1010 static smb_ucs2_t sep_list[] = { (smb_ucs2_t)' ', (smb_ucs2_t)'\t', (smb_ucs2_t)'\n', (smb_ucs2_t)'\r', 0};
1011 static smb_ucs2_t quotechar = (smb_ucs2_t)'\"';
1013 BOOL next_token_w(smb_ucs2_t **ptr, smb_ucs2_t *buff, smb_ucs2_t *sep, size_t bufsize)
1015 smb_ucs2_t *s;
1016 BOOL quoted;
1017 size_t len=1;
1020 * Convert bufsize to smb_ucs2_t units.
1023 bufsize /= sizeof(smb_ucs2_t);
1025 if (!ptr)
1026 ptr = &last_ptr;
1027 if (!ptr)
1028 return(False);
1030 s = *ptr;
1033 * Default to simple separators.
1036 if (!sep)
1037 sep = sep_list;
1040 * Find the first non sep char.
1043 while(*s && strchr_w(sep,*s))
1044 s++;
1047 * Nothing left ?
1050 if (!*s)
1051 return(False);
1054 * Copy over the token.
1057 for (quoted = False; len < bufsize && *s && (quoted || !strchr_w(sep,*s)); s++) {
1058 if (*s == quotechar) {
1059 quoted = !quoted;
1060 } else {
1061 len++;
1062 *buff++ = *s;
1066 *ptr = (*s) ? s+1 : s;
1067 *buff = 0;
1068 last_ptr = *ptr;
1070 return(True);
1073 /****************************************************************************
1074 Convert list of tokens to array; dependent on above routine.
1075 Uses last_ptr from above - bit of a hack.
1076 ****************************************************************************/
1078 smb_ucs2_t **toktocliplist_w(int *ctok, smb_ucs2_t *sep)
1080 smb_ucs2_t *s=last_ptr;
1081 int ictok=0;
1082 smb_ucs2_t **ret, **iret;
1084 if (!sep)
1085 sep = sep_list;
1087 while(*s && strchr_w(sep,*s))
1088 s++;
1091 * Nothing left ?
1094 if (!*s)
1095 return(NULL);
1097 do {
1098 ictok++;
1099 while(*s && (!strchr_w(sep,*s)))
1100 s++;
1101 while(*s && strchr_w(sep,*s))
1102 *s++=0;
1103 } while(*s);
1105 *ctok = ictok;
1106 s = last_ptr;
1108 if (!(ret=iret=malloc(ictok*sizeof(smb_ucs2_t *))))
1109 return NULL;
1111 while(ictok--) {
1112 *iret++=s;
1113 while(*s++)
1115 while(!*s)
1116 s++;
1119 return ret;
1122 /*******************************************************************
1123 Case insensitive string compararison.
1124 ********************************************************************/
1126 int StrCaseCmp_w(const smb_ucs2_t *s, const smb_ucs2_t *t)
1129 * Compare until we run out of string, either t or s, or find a difference.
1132 while (*s && *t && toupper_w(*s) == toupper_w(*t)) {
1133 s++;
1134 t++;
1137 return(toupper_w(*s) - toupper_w(*t));
1140 /*******************************************************************
1141 Case insensitive string compararison, length limited.
1142 n is in ucs2 units.
1143 ********************************************************************/
1145 int StrnCaseCmp_w(const smb_ucs2_t *s, const smb_ucs2_t *t, size_t n)
1148 * Compare until we run out of string, either t or s, or chars.
1151 while (n && *s && *t && toupper_w(*s) == toupper_w(*t)) {
1152 s++;
1153 t++;
1154 n--;
1158 * Not run out of chars - strings are different lengths.
1161 if (n)
1162 return(toupper_w(*s) - toupper_w(*t));
1165 * Identical up to where we run out of chars,
1166 * and strings are same length.
1169 return(0);
1172 /*******************************************************************
1173 Compare 2 strings.
1174 ********************************************************************/
1176 BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
1178 if (s1 == s2)
1179 return(True);
1180 if (!s1 || !s2)
1181 return(False);
1183 return(StrCaseCmp_w(s1,s2)==0);
1186 /*******************************************************************
1187 Compare 2 strings up to and including the nth char. n is in ucs2
1188 units.
1189 ******************************************************************/
1191 BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
1193 if (s1 == s2)
1194 return(True);
1195 if (!s1 || !s2 || !n)
1196 return(False);
1198 return(StrnCaseCmp_w(s1,s2,n)==0);
1201 /*******************************************************************
1202 Compare 2 strings (case sensitive).
1203 ********************************************************************/
1205 BOOL strcsequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2)
1207 if (s1 == s2)
1208 return(True);
1209 if (!s1 || !s2)
1210 return(False);
1212 return(strcmp_w(s1,s2)==0);
1215 /*******************************************************************
1216 Convert a string to lower case.
1217 ********************************************************************/
1219 void strlower_w(smb_ucs2_t *s)
1221 while (*s) {
1222 if (isupper_w(*s))
1223 *s = tolower_w(*s);
1224 s++;
1228 /*******************************************************************
1229 Convert a string to upper case.
1230 ********************************************************************/
1232 void strupper_w(smb_ucs2_t *s)
1234 while (*s) {
1235 if (islower_w(*s))
1236 *s = toupper_w(*s);
1237 s++;
1241 /*******************************************************************
1242 Convert a string to "normal" form.
1243 ********************************************************************/
1245 void strnorm_w(smb_ucs2_t *s)
1247 extern int case_default;
1248 if (case_default == CASE_UPPER)
1249 strupper_w(s);
1250 else
1251 strlower_w(s);
1254 /*******************************************************************
1255 Check if a string is in "normal" case.
1256 ********************************************************************/
1258 BOOL strisnormal_w(smb_ucs2_t *s)
1260 extern int case_default;
1261 if (case_default == CASE_UPPER)
1262 return(!strhaslower_w(s));
1264 return(!strhasupper_w(s));
1267 /****************************************************************************
1268 String replace.
1269 ****************************************************************************/
1271 void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc)
1273 while (*s) {
1274 if (oldc == *s)
1275 *s = newc;
1276 s++;
1280 /*******************************************************************
1281 Skip past some strings in a buffer. n is in bytes.
1282 ********************************************************************/
1284 smb_ucs2_t *skip_string_w(smb_ucs2_t *buf,size_t n)
1286 while (n--)
1287 buf += (strlen_w(buf)*sizeof(smb_ucs2_t)) + 1;
1288 return(buf);
1291 /*******************************************************************
1292 Count the number of characters in a string. Same as strlen_w in
1293 smb_ucs2_t string units.
1294 ********************************************************************/
1296 size_t str_charnum_w(const smb_ucs2_t *s)
1298 return strlen_w(s);
1301 /*******************************************************************
1302 Trim the specified elements off the front and back of a string.
1303 ********************************************************************/
1305 BOOL trim_string_w(smb_ucs2_t *s,const smb_ucs2_t *front,const smb_ucs2_t *back)
1307 BOOL ret = False;
1308 size_t front_len = (front && *front) ? strlen_w(front) : 0;
1309 size_t back_len = (back && *back) ? strlen_w(back) : 0;
1310 size_t s_len;
1312 while (front_len && strncmp_w(s, front, front_len) == 0) {
1313 smb_ucs2_t *p = s;
1314 ret = True;
1316 while (1) {
1317 if (!(*p = p[front_len]))
1318 break;
1319 p++;
1323 if(back_len) {
1324 s_len = strlen_w(s);
1325 while ((s_len >= back_len) &&
1326 (strncmp_w(s + s_len - back_len, back, back_len)==0)) {
1327 ret = True;
1328 s[s_len - back_len] = 0;
1329 s_len = strlen_w(s);
1333 return(ret);
1336 /****************************************************************************
1337 Does a string have any uppercase chars in it ?
1338 ****************************************************************************/
1340 BOOL strhasupper_w(const smb_ucs2_t *s)
1342 while (*s) {
1343 if (isupper_w(*s))
1344 return(True);
1345 s++;
1347 return(False);
1350 /****************************************************************************
1351 Does a string have any lowercase chars in it ?
1352 ****************************************************************************/
1354 BOOL strhaslower_w(const smb_ucs2_t *s)
1356 while (*s) {
1357 if (islower(*s))
1358 return(True);
1359 s++;
1361 return(False);
1364 /****************************************************************************
1365 Find the number of 'c' chars in a string.
1366 ****************************************************************************/
1368 size_t count_chars_w(const smb_ucs2_t *s,smb_ucs2_t c)
1370 size_t count=0;
1372 while (*s) {
1373 if (*s == c)
1374 count++;
1375 s++;
1377 return(count);
1380 /*******************************************************************
1381 Return True if a string consists only of one particular character.
1382 ********************************************************************/
1384 BOOL str_is_all_w(const smb_ucs2_t *s,smb_ucs2_t c)
1386 if(s == NULL)
1387 return False;
1388 if(!*s)
1389 return False;
1391 while (*s) {
1392 if (*s != c)
1393 return False;
1394 s++;
1396 return True;
1399 /*******************************************************************
1400 Paranoid strcpy into a buffer of given length (includes terminating
1401 zero. Strips out all but 'a-Z0-9' and replaces with '_'. Deliberately
1402 does *NOT* check for multibyte characters. Don't change it !
1403 maxlength is in ucs2 units.
1404 ********************************************************************/
1406 smb_ucs2_t *alpha_strcpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, size_t maxlength)
1408 size_t len, i;
1410 if (!dest) {
1411 DEBUG(0,("ERROR: NULL dest in alpha_strcpy_w\n"));
1412 return NULL;
1415 if (!src) {
1416 *dest = 0;
1417 return dest;
1420 len = strlen_w(src);
1421 if (len >= maxlength)
1422 len = maxlength - 1;
1424 for(i = 0; i < len; i++) {
1425 smb_ucs2_t val = src[i];
1426 if(isupper_w(val) ||islower_w(val) || isdigit_w(val))
1427 dest[i] = src[i];
1428 else
1429 dest[i] = (smb_ucs2_t)'_';
1432 dest[i] = 0;
1434 return dest;
1437 /****************************************************************************
1438 Like strncpy but always null terminates. Make sure there is room !
1439 The variable n should always be one less than the available size and is in
1440 ucs2 units.
1441 ****************************************************************************/
1443 smb_ucs2_t *StrnCpy_w(smb_ucs2_t *dest,const smb_ucs2_t *src,size_t n)
1445 smb_ucs2_t *d = dest;
1446 if (!dest)
1447 return(NULL);
1448 if (!src) {
1449 *dest = 0;
1450 return(dest);
1453 while (n-- && (*d++ = *src++))
1455 *d = 0;
1456 return(dest);
1459 /****************************************************************************
1460 Like strncpy but copies up to the character marker. Always null terminates.
1461 returns a pointer to the character marker in the source string (src).
1462 n is in ucs2 units.
1463 ****************************************************************************/
1465 smb_ucs2_t *strncpyn_w(smb_ucs2_t *dest, const smb_ucs2_t *src,size_t n, smb_ucs2_t c)
1467 smb_ucs2_t *p;
1468 size_t str_len;
1470 p = strchr_w(src, c);
1471 if (p == NULL) {
1472 fstring cval;
1473 smb_ucs2_t mbcval[2];
1474 mbcval[0] = c;
1475 mbcval[1] = 0;
1476 DEBUG(5, ("strncpyn_w: separator character (%s) not found\n",
1477 unicode_to_unix(cval,mbcval,sizeof(cval)) ));
1478 return NULL;
1481 str_len = PTR_DIFF(p, src) + 1;
1482 safe_strcpy_w(dest, src, MIN(n, str_len));
1484 return p;
1487 /*************************************************************
1488 Routine to get hex characters and turn them into a 16 byte array.
1489 The array can be variable length, and any non-hex-numeric
1490 characters are skipped. "0xnn" or "0Xnn" is specially catered
1491 for. len is in bytes.
1492 Valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
1493 **************************************************************/
1495 static smb_ucs2_t hexprefix[] = { (smb_ucs2_t)'0', (smb_ucs2_t)'x', 0 };
1496 static smb_ucs2_t hexchars[] = { (smb_ucs2_t)'0', (smb_ucs2_t)'1', (smb_ucs2_t)'2', (smb_ucs2_t)'3',
1497 (smb_ucs2_t)'4', (smb_ucs2_t)'5', (smb_ucs2_t)'6', (smb_ucs2_t)'7',
1498 (smb_ucs2_t)'8', (smb_ucs2_t)'9', (smb_ucs2_t)'A', (smb_ucs2_t)'B',
1499 (smb_ucs2_t)'C', (smb_ucs2_t)'D', (smb_ucs2_t)'E', (smb_ucs2_t)'F', 0 };
1501 size_t strhex_to_str_w(char *p, size_t len, const smb_ucs2_t *strhex)
1503 size_t i;
1504 size_t num_chars = 0;
1505 unsigned char lonybble, hinybble;
1506 smb_ucs2_t *p1 = NULL, *p2 = NULL;
1509 * Convert to smb_ucs2_t units.
1512 len /= sizeof(smb_ucs2_t);
1514 for (i = 0; i < len && strhex[i] != 0; i++) {
1515 if (strnequal_w(hexchars, hexprefix, 2)) {
1516 i++; /* skip two chars */
1517 continue;
1520 if (!(p1 = strchr_w(hexchars, toupper_w(strhex[i]))))
1521 break;
1523 i++; /* next hex digit */
1525 if (!(p2 = strchr_w(hexchars, toupper_w(strhex[i]))))
1526 break;
1528 /* get the two nybbles */
1529 hinybble = (PTR_DIFF(p1, hexchars)/sizeof(smb_ucs2_t));
1530 lonybble = (PTR_DIFF(p2, hexchars)/sizeof(smb_ucs2_t));
1532 p[num_chars] = (hinybble << 4) | lonybble;
1533 num_chars++;
1535 p1 = NULL;
1536 p2 = NULL;
1538 return num_chars;
1541 /****************************************************************************
1542 Check if a string is part of a list.
1543 ****************************************************************************/
1545 BOOL in_list_w(smb_ucs2_t *s,smb_ucs2_t *list,BOOL casesensitive)
1547 wpstring tok;
1548 smb_ucs2_t *p=list;
1550 if (!list)
1551 return(False);
1553 while (next_token_w(&p,tok,LIST_SEP_W,sizeof(tok))) {
1554 if (casesensitive) {
1555 if (strcmp_w(tok,s) == 0)
1556 return(True);
1557 } else {
1558 if (StrCaseCmp_w(tok,s) == 0)
1559 return(True);
1562 return(False);
1565 /* This is used to prevent lots of mallocs of size 2 */
1566 static smb_ucs2_t *null_string = NULL;
1568 /****************************************************************************
1569 Set a string value, allocing the space for the string.
1570 ****************************************************************************/
1572 BOOL string_init_w(smb_ucs2_t **dest,const smb_ucs2_t *src)
1574 size_t l;
1576 if (!null_string) {
1577 if((null_string = (smb_ucs2_t *)malloc(sizeof(smb_ucs2_t))) == NULL) {
1578 DEBUG(0,("string_init_w: malloc fail for null_string.\n"));
1579 return False;
1581 *null_string = 0;
1584 if (!src)
1585 src = null_string;
1587 l = strlen_w(src);
1589 if (l == 0)
1590 *dest = null_string;
1591 else {
1592 (*dest) = (smb_ucs2_t *)malloc(sizeof(smb_ucs2_t)*(l+1));
1593 if ((*dest) == NULL) {
1594 DEBUG(0,("Out of memory in string_init_w\n"));
1595 return False;
1598 wpstrcpy(*dest,src);
1600 return(True);
1603 /****************************************************************************
1604 Free a string value.
1605 ****************************************************************************/
1607 void string_free_w(smb_ucs2_t **s)
1609 if (!s || !(*s))
1610 return;
1611 if (*s == null_string)
1612 *s = NULL;
1613 if (*s)
1614 free((char *)*s);
1615 *s = NULL;
1618 /****************************************************************************
1619 Set a string value, allocing the space for the string, and deallocating any
1620 existing space.
1621 ****************************************************************************/
1623 BOOL string_set_w(smb_ucs2_t **dest,const smb_ucs2_t *src)
1625 string_free_w(dest);
1627 return(string_init_w(dest,src));
1630 /****************************************************************************
1631 Substitute a string for a pattern in another string. Make sure there is
1632 enough room !
1634 This routine looks for pattern in s and replaces it with
1635 insert. It may do multiple replacements.
1637 Any of " ; ' $ or ` in the insert string are replaced with _
1638 if len==0 then no length check is performed
1639 len is in ucs2 units.
1640 ****************************************************************************/
1642 void string_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert, size_t len)
1644 smb_ucs2_t *p;
1645 ssize_t ls,lp,li, i;
1647 if (!insert || !pattern || !s)
1648 return;
1650 ls = (ssize_t)strlen_w(s);
1651 lp = (ssize_t)strlen_w(pattern);
1652 li = (ssize_t)strlen_w(insert);
1654 if (!*pattern)
1655 return;
1657 while (lp <= ls && (p = strstr_w(s,pattern))) {
1658 if (len && (ls + (li-lp) >= len)) {
1659 fstring out;
1660 DEBUG(0,("ERROR: string overflow by %d in string_sub_w(%.50s, %d)\n",
1661 (int)(sizeof(smb_ucs2_t)*(ls + (li-lp) - len)),
1662 unicode_to_unix(out,pattern,sizeof(out)), (int)len*sizeof(smb_ucs2_t)));
1663 break;
1665 if (li != lp)
1666 memmove(p+li,p+lp,sizeof(smb_ucs2_t)*(strlen_w(p+lp)+1));
1668 for (i=0;i<li;i++) {
1669 switch (insert[i]) {
1670 case (smb_ucs2_t)'`':
1671 case (smb_ucs2_t)'"':
1672 case (smb_ucs2_t)'\'':
1673 case (smb_ucs2_t)';':
1674 case (smb_ucs2_t)'$':
1675 case (smb_ucs2_t)'%':
1676 case (smb_ucs2_t)'\r':
1677 case (smb_ucs2_t)'\n':
1678 p[i] = (smb_ucs2_t)'_';
1679 break;
1680 default:
1681 p[i] = insert[i];
1684 s = p + li;
1685 ls += (li-lp);
1689 void fstring_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert)
1691 string_sub_w(s, pattern, insert, sizeof(wfstring));
1694 void pstring_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,smb_ucs2_t *insert)
1696 string_sub_w(s, pattern, insert, sizeof(wpstring));
1699 /****************************************************************************
1700 Similar to string_sub() but allows for any character to be substituted.
1701 Use with caution !
1702 if len==0 then no length check is performed.
1703 ****************************************************************************/
1705 void all_string_sub_w(smb_ucs2_t *s,const smb_ucs2_t *pattern,const smb_ucs2_t *insert, size_t len)
1707 smb_ucs2_t *p;
1708 ssize_t ls,lp,li;
1710 if (!insert || !pattern || !s)
1711 return;
1713 ls = (ssize_t)strlen_w(s);
1714 lp = (ssize_t)strlen_w(pattern);
1715 li = (ssize_t)strlen_w(insert);
1717 if (!*pattern)
1718 return;
1720 while (lp <= ls && (p = strstr_w(s,pattern))) {
1721 if (len && (ls + (li-lp) >= len)) {
1722 fstring out;
1723 DEBUG(0,("ERROR: string overflow by %d in all_string_sub_w(%.50s, %d)\n",
1724 (int)(sizeof(smb_ucs2_t)*(ls + (li-lp) - len)),
1725 unicode_to_unix(out,pattern,sizeof(out)), (int)len*sizeof(smb_ucs2_t)));
1726 break;
1728 if (li != lp)
1729 memmove(p+li,p+lp,sizeof(smb_ucs2_t)*(strlen_w(p+lp)+1));
1731 memcpy(p, insert, li*sizeof(smb_ucs2_t));
1732 s = p + li;
1733 ls += (li-lp);
1737 /****************************************************************************
1738 Splits out the front and back at a separator.
1739 ****************************************************************************/
1741 void split_at_last_component_w(smb_ucs2_t *path, smb_ucs2_t *front, smb_ucs2_t sep, smb_ucs2_t *back)
1743 smb_ucs2_t *p = strrchr_w(path, sep);
1745 if (p != NULL)
1746 *p = 0;
1748 if (front != NULL)
1749 wpstrcpy(front, path);
1751 if (p != NULL) {
1752 if (back != NULL)
1753 wpstrcpy(back, p+1);
1754 *p = (smb_ucs2_t)'\\';
1755 } else {
1756 if (back != NULL)
1757 back[0] = 0;
1762 /****************************************************************************
1763 Write an octal as a string.
1764 ****************************************************************************/
1766 smb_ucs2_t *octal_string_w(int i)
1768 static smb_ucs2_t wret[64];
1769 char ret[64];
1771 if (i == -1)
1772 slprintf(ret, sizeof(ret), "-1");
1773 else
1774 slprintf(ret, sizeof(ret), "0%o", i);
1775 return unix_to_unicode(wret, ret, sizeof(wret));
1779 /****************************************************************************
1780 Truncate a string at a specified length.
1781 length is in ucs2 units.
1782 ****************************************************************************/
1784 smb_ucs2_t *string_truncate_w(smb_ucs2_t *s, size_t length)
1786 if (s && strlen_w(s) > length)
1787 s[length] = 0;
1789 return s;