2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-2001
6 Copyright (C) Simo Sorce 2001-2002
7 Copyright (C) Martin Pool 2003
8 Copyright (C) James Peach 2006
9 Copyright (C) Jeremy Allison 1992-2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 char toupper_ascii_fast_table[128] = {
28 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
29 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
30 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
31 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
32 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
33 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
34 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
35 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
40 * @brief String utilities.
43 static bool next_token_internal_talloc(TALLOC_CTX *ctx,
62 /* default to simple separators */
67 /* find the first non sep char, if left-trimming is requested */
69 while (*s && strchr_m(sep,*s)) {
79 /* When restarting we need to go from here. */
82 /* Work out the length needed. */
83 for (quoted = false; *s &&
84 (quoted || !strchr_m(sep,*s)); s++) {
92 /* We started with len = 1 so we have space for the nul. */
93 *pp_buff = TALLOC_ARRAY(ctx, char, len);
98 /* copy over the token */
101 for (quoted = false; *s &&
102 (quoted || !strchr_m(sep,*s)); s++) {
110 *ptr = (*s) ? s+1 : s;
118 * Get the next token from a string, return false if none found. Handles
119 * double-quotes. This version trims leading separator characters before
120 * looking for a token.
122 bool next_token(const char **ptr, char *buff, const char *sep, size_t bufsize)
124 return next_token_internal(ptr, buff, sep, bufsize, true);
128 bool next_token_talloc(TALLOC_CTX *ctx,
133 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
137 * Get the next token from a string, return false if none found. Handles
138 * double-quotes. This version does not trim leading separator characters
139 * before looking for a token.
142 bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
147 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
151 * Case insensitive string compararison.
153 * iconv does not directly give us a way to compare strings in
154 * arbitrary unix character sets -- all we can is convert and then
155 * compare. This is expensive.
157 * As an optimization, we do a first pass that considers only the
158 * prefix of the strings that is entirely 7-bit. Within this, we
159 * check whether they have the same value.
161 * Hopefully this will often give the answer without needing to copy.
162 * In particular it should speed comparisons to literal ascii strings
163 * or comparisons of strings that are "obviously" different.
165 * If we find a non-ascii character we fall back to converting via
168 * This should never be slower than convering the whole thing, and
171 * A different optimization would be to compare for bitwise equality
172 * in the binary encoding. (It would be possible thought hairy to do
173 * both simultaneously.) But in that case if they turn out to be
174 * different, we'd need to restart the whole thing.
176 * Even better is to implement strcasecmp for each encoding and use a
179 int StrCaseCmp(const char *s, const char *t)
184 smb_ucs2_t *buffer_s, *buffer_t;
187 for (ps = s, pt = t; ; ps++, pt++) {
191 return 0; /* both ended */
193 return -1; /* s is a prefix */
195 return +1; /* t is a prefix */
196 else if ((*ps & 0x80) || (*pt & 0x80))
197 /* not ascii anymore, do it the hard way
201 us = toupper_ascii_fast(*ps);
202 ut = toupper_ascii_fast(*pt);
211 if (!push_ucs2_allocate(&buffer_s, ps, &size)) {
212 return strcmp(ps, pt);
213 /* Not quite the right answer, but finding the right one
214 under this failure case is expensive, and it's pretty
218 if (!push_ucs2_allocate(&buffer_t, pt, &size)) {
220 return strcmp(ps, pt);
221 /* Not quite the right answer, but finding the right one
222 under this failure case is expensive, and it's pretty
226 ret = strcasecmp_w(buffer_s, buffer_t);
234 Case insensitive string compararison, length limited.
236 int StrnCaseCmp(const char *s, const char *t, size_t len)
241 smb_ucs2_t *buffer_s, *buffer_t;
244 for (ps = s, pt = t; n < len ; ps++, pt++, n++) {
248 return 0; /* both ended */
250 return -1; /* s is a prefix */
252 return +1; /* t is a prefix */
253 else if ((*ps & 0x80) || (*pt & 0x80))
254 /* not ascii anymore, do it the
255 * hard way from here on in */
258 us = toupper_ascii_fast(*ps);
259 ut = toupper_ascii_fast(*pt);
272 if (!push_ucs2_allocate(&buffer_s, ps, &size)) {
273 return strncmp(ps, pt, len-n);
274 /* Not quite the right answer, but finding the right one
275 under this failure case is expensive,
276 and it's pretty close */
279 if (!push_ucs2_allocate(&buffer_t, pt, &size)) {
281 return strncmp(ps, pt, len-n);
282 /* Not quite the right answer, but finding the right one
283 under this failure case is expensive,
284 and it's pretty close */
287 ret = strncasecmp_w(buffer_s, buffer_t, len-n);
296 * @note The comparison is case-insensitive.
298 bool strequal(const char *s1, const char *s2)
305 return(StrCaseCmp(s1,s2)==0);
309 * Compare 2 strings up to and including the nth char.
311 * @note The comparison is case-insensitive.
313 bool strnequal(const char *s1,const char *s2,size_t n)
317 if (!s1 || !s2 || !n)
320 return(StrnCaseCmp(s1,s2,n)==0);
324 Compare 2 strings (case sensitive).
327 bool strcsequal(const char *s1,const char *s2)
334 return(strcmp(s1,s2)==0);
338 Do a case-insensitive, whitespace-ignoring string compare.
341 int strwicmp(const char *psz1, const char *psz2)
343 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
344 /* appropriate value. */
347 else if (psz1 == NULL)
349 else if (psz2 == NULL)
352 /* sync the strings on first non-whitespace */
354 while (isspace((int)*psz1))
356 while (isspace((int)*psz2))
358 if (toupper_ascii(*psz1) != toupper_ascii(*psz2) ||
359 *psz1 == '\0' || *psz2 == '\0')
364 return (*psz1 - *psz2);
368 Convert a string to "normal" form.
371 void strnorm(char *s, int case_default)
373 if (case_default == CASE_UPPER)
380 Check if a string is in "normal" case.
383 bool strisnormal(const char *s, int case_default)
385 if (case_default == CASE_UPPER)
386 return(!strhaslower(s));
388 return(!strhasupper(s));
394 NOTE: oldc and newc must be 7 bit characters
396 void string_replace( char *s, char oldc, char newc )
400 /* this is quite a common operation, so we want it to be
401 fast. We optimise for the ascii case, knowing that all our
402 supported multi-byte character sets are ascii-compatible
403 (ie. they match for the first 128 chars) */
405 for (p = s; *p; p++) {
406 if (*p & 0x80) /* mb string - slow path. */
416 /* Slow (mb) path. */
417 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
418 /* With compose characters we must restart from the beginning. JRA. */
424 next_codepoint(p, &c_size);
436 * Skip past some strings in a buffer - old version - no checks.
439 char *push_skip_string(char *buf)
441 buf += strlen(buf) + 1;
446 Skip past a string in a buffer. Buffer may not be
447 null terminated. end_ptr points to the first byte after
448 then end of the buffer.
451 char *skip_string(const char *base, size_t len, char *buf)
453 const char *end_ptr = base + len;
455 if (end_ptr < base || !base || !buf || buf >= end_ptr) {
459 /* Skip the string */
462 if (buf >= end_ptr) {
472 Count the number of characters in a string. Normally this will
473 be the same as the number of bytes in a string for single byte strings,
474 but will be different for multibyte.
477 size_t str_charnum(const char *s)
479 size_t ret, converted_size;
480 smb_ucs2_t *tmpbuf2 = NULL;
481 if (!push_ucs2_allocate(&tmpbuf2, s, &converted_size)) {
484 ret = strlen_w(tmpbuf2);
490 Count the number of characters in a string. Normally this will
491 be the same as the number of bytes in a string for single byte strings,
492 but will be different for multibyte.
495 size_t str_ascii_charnum(const char *s)
497 size_t ret, converted_size;
498 char *tmpbuf2 = NULL;
499 if (!push_ascii_allocate(&tmpbuf2, s, &converted_size)) {
502 ret = strlen(tmpbuf2);
507 bool trim_char(char *s,char cfront,char cback)
513 /* Ignore null or empty strings. */
514 if (!s || (s[0] == '\0'))
518 while (*fp && *fp == cfront)
521 /* We ate the string. */
529 ep = fp + strlen(fp) - 1;
531 /* Attempt ascii only. Bail for mb strings. */
532 while ((ep >= fp) && (*ep == cback)) {
534 if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
535 /* Could be mb... bail back to tim_string. */
543 return trim_string(s, cfront ? fs : NULL, bs);
549 /* We ate the string. */
556 memmove(s, fp, ep-fp+2);
561 Trim the specified elements off the front and back of a string.
564 bool trim_string(char *s,const char *front,const char *back)
571 /* Ignore null or empty strings. */
572 if (!s || (s[0] == '\0'))
575 front_len = front? strlen(front) : 0;
576 back_len = back? strlen(back) : 0;
581 while (len && strncmp(s, front, front_len)==0) {
582 /* Must use memmove here as src & dest can
583 * easily overlap. Found by valgrind. JRA. */
584 memmove(s, s+front_len, (len-front_len)+1);
591 while ((len >= back_len) &&
592 strncmp(s+len-back_len,back,back_len)==0) {
593 s[len-back_len]='\0';
602 Does a string have any uppercase chars in it?
605 bool strhasupper(const char *s)
609 size_t converted_size;
611 if (!push_ucs2_allocate(&tmp, s, &converted_size)) {
615 for(p = tmp; *p != 0; p++) {
627 Does a string have any lowercase chars in it?
630 bool strhaslower(const char *s)
634 size_t converted_size;
636 if (!push_ucs2_allocate(&tmp, s, &converted_size)) {
640 for(p = tmp; *p != 0; p++) {
652 Find the number of 'c' chars in a string
655 size_t count_chars(const char *s,char c)
659 smb_ucs2_t *alloc_tmpbuf = NULL;
660 size_t converted_size;
662 if (!push_ucs2_allocate(&alloc_tmpbuf, s, &converted_size)) {
666 for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++)
667 if(*ptr==UCS2_CHAR(c))
670 SAFE_FREE(alloc_tmpbuf);
675 Safe string copy into a known length string. maxlength does not
676 include the terminating zero.
679 char *safe_strcpy_fn(const char *fn,
688 DEBUG(0,("ERROR: NULL dest in safe_strcpy, "
689 "called from [%s][%d]\n", fn, line));
694 clobber_region(fn,line,dest, maxlength+1);
702 len = strnlen(src, maxlength+1);
704 if (len > maxlength) {
705 DEBUG(0,("ERROR: string overflow by "
706 "%lu (%lu - %lu) in safe_strcpy [%.50s]\n",
707 (unsigned long)(len-maxlength), (unsigned long)len,
708 (unsigned long)maxlength, src));
712 memmove(dest, src, len);
718 Safe string cat into a string. maxlength does not
719 include the terminating zero.
721 char *safe_strcat_fn(const char *fn,
727 size_t src_len, dest_len;
730 DEBUG(0,("ERROR: NULL dest in safe_strcat, "
731 "called from [%s][%d]\n", fn, line));
738 src_len = strnlen(src, maxlength + 1);
739 dest_len = strnlen(dest, maxlength + 1);
742 clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
745 if (src_len + dest_len > maxlength) {
746 DEBUG(0,("ERROR: string overflow by %d "
747 "in safe_strcat [%.50s]\n",
748 (int)(src_len + dest_len - maxlength), src));
749 if (maxlength > dest_len) {
750 memcpy(&dest[dest_len], src, maxlength - dest_len);
756 memcpy(&dest[dest_len], src, src_len);
757 dest[dest_len + src_len] = 0;
762 Paranoid strcpy into a buffer of given length (includes terminating
763 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
764 and replaces with '_'. Deliberately does *NOT* check for multibyte
765 characters. Don't change it !
768 char *alpha_strcpy_fn(const char *fn,
772 const char *other_safe_chars,
778 clobber_region(fn, line, dest, maxlength);
782 DEBUG(0,("ERROR: NULL dest in alpha_strcpy, "
783 "called from [%s][%d]\n", fn, line));
793 if (len >= maxlength)
796 if (!other_safe_chars)
797 other_safe_chars = "";
799 for(i = 0; i < len; i++) {
800 int val = (src[i] & 0xff);
801 if (isupper_ascii(val) || islower_ascii(val) ||
802 isdigit(val) || strchr_m(other_safe_chars, val))
814 Like strncpy but always null terminates. Make sure there is room!
815 The variable n should always be one less than the available size.
817 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
822 clobber_region(fn, line, dest, n+1);
826 DEBUG(0,("ERROR: NULL dest in StrnCpy, "
827 "called from [%s][%d]\n", fn, line));
836 while (n-- && (*d = *src)) {
847 Like strncpy but copies up to the character marker. always null terminates.
848 returns a pointer to the character marker in the source string (src).
851 static char *strncpyn(char *dest, const char *src, size_t n, char c)
857 clobber_region(dest, n+1);
859 p = strchr_m(src, c);
861 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
865 str_len = PTR_DIFF(p, src);
866 strncpy(dest, src, MIN(n, str_len));
867 dest[str_len] = '\0';
874 Routine to get hex characters and turn them into a 16 byte array.
875 the array can be variable length, and any non-hex-numeric
876 characters are skipped. "0xnn" or "0Xnn" is specially catered
879 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
883 size_t strhex_to_str(char *buf, size_t buf_len, const char *strhex, size_t strhex_len)
886 size_t num_chars = 0;
887 unsigned char lonybble, hinybble;
888 const char *hexchars = "0123456789ABCDEF";
889 char *p1 = NULL, *p2 = NULL;
891 for (i = 0; i < strhex_len && strhex[i] != 0; i++) {
892 if (strnequal(hexchars, "0x", 2)) {
893 i++; /* skip two chars */
897 if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
900 i++; /* next hex digit */
902 if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
905 /* get the two nybbles */
906 hinybble = PTR_DIFF(p1, hexchars);
907 lonybble = PTR_DIFF(p2, hexchars);
909 if (num_chars >= buf_len) {
912 buf[num_chars] = (hinybble << 4) | lonybble;
921 DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
926 ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
928 ret_blob = data_blob(NULL, strlen(strhex)/2+1);
930 ret_blob.length = strhex_to_str((char*)ret_blob.data,
939 * Routine to print a buffer as HEX digits, into an allocated string.
942 char *hex_encode(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
947 hex_buffer = TALLOC_ARRAY(mem_ctx, char, (len*2)+1);
949 for (i = 0; i < len; i++)
950 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
956 Check if a string is part of a list.
959 bool in_list(const char *s, const char *list, bool casesensitive)
969 frame = talloc_stackframe();
970 while (next_token_talloc(frame, &list, &tok,LIST_SEP)) {
972 if (strcmp(tok,s) == 0) {
977 if (StrCaseCmp(tok,s) == 0) {
987 /* this is used to prevent lots of mallocs of size 1 */
988 static const char null_string[] = "";
991 Set a string value, allocing the space for the string
994 static bool string_init(char **dest,const char *src)
1004 *dest = CONST_DISCARD(char*, null_string);
1006 (*dest) = SMB_STRDUP(src);
1007 if ((*dest) == NULL) {
1008 DEBUG(0,("Out of memory in string_init\n"));
1016 Free a string value.
1019 void string_free(char **s)
1023 if (*s == null_string)
1029 Set a string value, deallocating any existing space, and allocing the space
1033 bool string_set(char **dest,const char *src)
1036 return(string_init(dest,src));
1040 Substitute a string for a pattern in another string. Make sure there is
1043 This routine looks for pattern in s and replaces it with
1044 insert. It may do multiple replacements or just one.
1046 Any of " ; ' $ or ` in the insert string are replaced with _
1047 if len==0 then the string cannot be extended. This is different from the old
1048 use of len==0 which was for no length checks to be done.
1051 void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
1052 bool remove_unsafe_characters, bool replace_once,
1053 bool allow_trailing_dollar)
1056 ssize_t ls,lp,li, i;
1058 if (!insert || !pattern || !*pattern || !s)
1061 ls = (ssize_t)strlen(s);
1062 lp = (ssize_t)strlen(pattern);
1063 li = (ssize_t)strlen(insert);
1066 len = ls + 1; /* len is number of *bytes* */
1068 while (lp <= ls && (p = strstr_m(s,pattern))) {
1069 if (ls + (li-lp) >= len) {
1070 DEBUG(0,("ERROR: string overflow by "
1071 "%d in string_sub(%.50s, %d)\n",
1072 (int)(ls + (li-lp) - len),
1073 pattern, (int)len));
1077 memmove(p+li,p+lp,strlen(p+lp)+1);
1079 for (i=0;i<li;i++) {
1080 switch (insert[i]) {
1086 /* allow a trailing $
1087 * (as in machine accounts) */
1088 if (allow_trailing_dollar && (i == li - 1 )) {
1095 if ( remove_unsafe_characters ) {
1097 /* yes this break should be here
1098 * since we want to fall throw if
1099 * not replacing unsafe chars */
1114 void string_sub_once(char *s, const char *pattern,
1115 const char *insert, size_t len)
1117 string_sub2( s, pattern, insert, len, true, true, false );
1120 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
1122 string_sub2( s, pattern, insert, len, true, false, false );
1125 void fstring_sub(char *s,const char *pattern,const char *insert)
1127 string_sub(s, pattern, insert, sizeof(fstring));
1131 Similar to string_sub2, but it will accept only allocated strings
1132 and may realloc them so pay attention at what you pass on no
1133 pointers inside strings, no const may be passed
1137 char *realloc_string_sub2(char *string,
1138 const char *pattern,
1140 bool remove_unsafe_characters,
1141 bool allow_trailing_dollar)
1145 ssize_t ls,lp,li,ld, i;
1147 if (!insert || !pattern || !*pattern || !string || !*string)
1152 in = SMB_STRDUP(insert);
1154 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1157 ls = (ssize_t)strlen(s);
1158 lp = (ssize_t)strlen(pattern);
1159 li = (ssize_t)strlen(insert);
1161 for (i=0;i<li;i++) {
1168 /* allow a trailing $
1169 * (as in machine accounts) */
1170 if (allow_trailing_dollar && (i == li - 1 )) {
1176 if ( remove_unsafe_characters ) {
1186 while ((p = strstr_m(s,pattern))) {
1188 int offset = PTR_DIFF(s,string);
1189 string = (char *)SMB_REALLOC(string, ls + ld + 1);
1191 DEBUG(0, ("realloc_string_sub: "
1192 "out of memory!\n"));
1196 p = string + offset + (p - s);
1199 memmove(p+li,p+lp,strlen(p+lp)+1);
1209 char *realloc_string_sub(char *string,
1210 const char *pattern,
1213 return realloc_string_sub2(string, pattern, insert, true, false);
1217 * Internal guts of talloc_string_sub and talloc_all_string_sub.
1218 * talloc version of string_sub2.
1221 char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
1222 const char *pattern,
1224 bool remove_unsafe_characters,
1226 bool allow_trailing_dollar)
1231 ssize_t ls,lp,li,ld, i;
1233 if (!insert || !pattern || !*pattern || !src) {
1237 string = talloc_strdup(mem_ctx, src);
1238 if (string == NULL) {
1239 DEBUG(0, ("talloc_string_sub2: "
1240 "talloc_strdup failed\n"));
1246 in = SMB_STRDUP(insert);
1248 DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
1251 ls = (ssize_t)strlen(s);
1252 lp = (ssize_t)strlen(pattern);
1253 li = (ssize_t)strlen(insert);
1256 for (i=0;i<li;i++) {
1263 /* allow a trailing $
1264 * (as in machine accounts) */
1265 if (allow_trailing_dollar && (i == li - 1 )) {
1271 if (remove_unsafe_characters) {
1281 while ((p = strstr_m(s,pattern))) {
1283 int offset = PTR_DIFF(s,string);
1284 string = (char *)TALLOC_REALLOC(mem_ctx, string,
1287 DEBUG(0, ("talloc_string_sub: out of "
1292 p = string + offset + (p - s);
1295 memmove(p+li,p+lp,strlen(p+lp)+1);
1309 /* Same as string_sub, but returns a talloc'ed string */
1311 char *talloc_string_sub(TALLOC_CTX *mem_ctx,
1313 const char *pattern,
1316 return talloc_string_sub2(mem_ctx, src, pattern, insert,
1317 true, false, false);
1321 Similar to string_sub() but allows for any character to be substituted.
1323 if len==0 then the string cannot be extended. This is different from the old
1324 use of len==0 which was for no length checks to be done.
1327 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1332 if (!insert || !pattern || !s)
1335 ls = (ssize_t)strlen(s);
1336 lp = (ssize_t)strlen(pattern);
1337 li = (ssize_t)strlen(insert);
1343 len = ls + 1; /* len is number of *bytes* */
1345 while (lp <= ls && (p = strstr_m(s,pattern))) {
1346 if (ls + (li-lp) >= len) {
1347 DEBUG(0,("ERROR: string overflow by "
1348 "%d in all_string_sub(%.50s, %d)\n",
1349 (int)(ls + (li-lp) - len),
1350 pattern, (int)len));
1354 memmove(p+li,p+lp,strlen(p+lp)+1);
1356 memcpy(p, insert, li);
1362 char *talloc_all_string_sub(TALLOC_CTX *ctx,
1364 const char *pattern,
1367 return talloc_string_sub2(ctx, src, pattern, insert,
1368 false, false, false);
1372 Write an octal as a string.
1375 char *octal_string(int i)
1379 result = talloc_strdup(talloc_tos(), "-1");
1382 result = talloc_asprintf(talloc_tos(), "0%o", i);
1384 SMB_ASSERT(result != NULL);
1390 Truncate a string at a specified length.
1393 char *string_truncate(char *s, unsigned int length)
1395 if (s && strlen(s) > length)
1401 Strchr and strrchr_m are very hard to do on general multi-byte strings.
1402 We convert via ucs2 for now.
1405 char *strchr_m(const char *src, char c)
1407 smb_ucs2_t *ws = NULL;
1412 size_t converted_size;
1414 /* characters below 0x3F are guaranteed to not appear in
1415 non-initial position in multi-byte charsets */
1416 if ((c & 0xC0) == 0) {
1417 return strchr(src, c);
1420 /* this is quite a common operation, so we want it to be
1421 fast. We optimise for the ascii case, knowing that all our
1422 supported multi-byte character sets are ascii-compatible
1423 (ie. they match for the first 128 chars) */
1425 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1433 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1434 /* With compose characters we must restart from the beginning. JRA. */
1438 if (!push_ucs2_allocate(&ws, s, &converted_size)) {
1439 /* Wrong answer, but what can we do... */
1440 return strchr(src, c);
1442 p = strchr_w(ws, UCS2_CHAR(c));
1448 if (!pull_ucs2_allocate(&s2, ws, &converted_size)) {
1450 /* Wrong answer, but what can we do... */
1451 return strchr(src, c);
1453 ret = (char *)(s+strlen(s2));
1459 char *strrchr_m(const char *s, char c)
1461 /* characters below 0x3F are guaranteed to not appear in
1462 non-initial position in multi-byte charsets */
1463 if ((c & 0xC0) == 0) {
1464 return strrchr(s, c);
1467 /* this is quite a common operation, so we want it to be
1468 fast. We optimise for the ascii case, knowing that all our
1469 supported multi-byte character sets are ascii-compatible
1470 (ie. they match for the first 128 chars). Also, in Samba
1471 we only search for ascii characters in 'c' and that
1472 in all mb character sets with a compound character
1473 containing c, if 'c' is not a match at position
1474 p, then p[-1] > 0x7f. JRA. */
1477 size_t len = strlen(s);
1479 bool got_mb = false;
1486 /* Could be a match. Part of a multibyte ? */
1488 (((unsigned char)cp[-1]) & 0x80)) {
1489 /* Yep - go slow :-( */
1493 /* No - we have a match ! */
1496 } while (cp-- != s);
1501 /* String contained a non-ascii char. Slow path. */
1503 smb_ucs2_t *ws = NULL;
1507 size_t converted_size;
1509 if (!push_ucs2_allocate(&ws, s, &converted_size)) {
1510 /* Wrong answer, but what can we do. */
1511 return strrchr(s, c);
1513 p = strrchr_w(ws, UCS2_CHAR(c));
1519 if (!pull_ucs2_allocate(&s2, ws, &converted_size)) {
1521 /* Wrong answer, but what can we do. */
1522 return strrchr(s, c);
1524 ret = (char *)(s+strlen(s2));
1531 /***********************************************************************
1532 Return the equivalent of doing strrchr 'n' times - always going
1534 ***********************************************************************/
1536 char *strnrchr_m(const char *s, char c, unsigned int n)
1538 smb_ucs2_t *ws = NULL;
1542 size_t converted_size;
1544 if (!push_ucs2_allocate(&ws, s, &converted_size)) {
1545 /* Too hard to try and get right. */
1548 p = strnrchr_w(ws, UCS2_CHAR(c), n);
1554 if (!pull_ucs2_allocate(&s2, ws, &converted_size)) {
1556 /* Too hard to try and get right. */
1559 ret = (char *)(s+strlen(s2));
1565 /***********************************************************************
1566 strstr_m - We convert via ucs2 for now.
1567 ***********************************************************************/
1569 char *strstr_m(const char *src, const char *findstr)
1572 smb_ucs2_t *src_w, *find_w;
1577 size_t converted_size, findstr_len = 0;
1579 /* for correctness */
1584 /* Samba does single character findstr calls a *lot*. */
1585 if (findstr[1] == '\0')
1586 return strchr_m(src, *findstr);
1588 /* We optimise for the ascii case, knowing that all our
1589 supported multi-byte character sets are ascii-compatible
1590 (ie. they match for the first 128 chars) */
1592 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1593 if (*s == *findstr) {
1595 findstr_len = strlen(findstr);
1597 if (strncmp(s, findstr, findstr_len) == 0) {
1606 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
1607 /* 'make check' fails unless we do this */
1609 /* With compose characters we must restart from the beginning. JRA. */
1613 if (!push_ucs2_allocate(&src_w, src, &converted_size)) {
1614 DEBUG(0,("strstr_m: src malloc fail\n"));
1618 if (!push_ucs2_allocate(&find_w, findstr, &converted_size)) {
1620 DEBUG(0,("strstr_m: find malloc fail\n"));
1624 p = strstr_w(src_w, find_w);
1633 if (!pull_ucs2_allocate(&s2, src_w, &converted_size)) {
1636 DEBUG(0,("strstr_m: dest malloc fail\n"));
1639 retp = (char *)(s+strlen(s2));
1647 Convert a string to lower case.
1650 void strlower_m(char *s)
1655 /* this is quite a common operation, so we want it to be
1656 fast. We optimise for the ascii case, knowing that all our
1657 supported multi-byte character sets are ascii-compatible
1658 (ie. they match for the first 128 chars) */
1660 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1661 *s = tolower_ascii((unsigned char)*s);
1668 /* I assume that lowercased string takes the same number of bytes
1669 * as source string even in UTF-8 encoding. (VIV) */
1670 len = strlen(s) + 1;
1673 unix_strlower(s,len,s,len);
1674 /* Catch mb conversion errors that may not terminate. */
1681 Convert a string to upper case.
1684 void strupper_m(char *s)
1689 /* this is quite a common operation, so we want it to be
1690 fast. We optimise for the ascii case, knowing that all our
1691 supported multi-byte character sets are ascii-compatible
1692 (ie. they match for the first 128 chars) */
1694 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1695 *s = toupper_ascii_fast((unsigned char)*s);
1702 /* I assume that lowercased string takes the same number of bytes
1703 * as source string even in multibyte encoding. (VIV) */
1704 len = strlen(s) + 1;
1707 unix_strupper(s,len,s,len);
1708 /* Catch mb conversion errors that may not terminate. */
1715 Count the number of UCS2 characters in a string. Normally this will
1716 be the same as the number of bytes in a string for single byte strings,
1717 but will be different for multibyte.
1720 size_t strlen_m(const char *s)
1728 while (*s && !(((uint8_t)*s) & 0x80)) {
1739 codepoint_t c = next_codepoint(s, &c_size);
1741 /* Unicode char fits into 16 bits. */
1744 /* Double-width unicode char - 32 bits. */
1754 Count the number of UCS2 characters in a string including the null
1758 size_t strlen_m_term(const char *s)
1763 return strlen_m(s) + 1;
1767 * Weird helper routine for the winreg pipe: If nothing is around, return 0,
1768 * if a string is there, include the terminator.
1771 size_t strlen_m_term_null(const char *s)
1785 Return a RFC2254 binary string representation of a buffer.
1786 Used in LDAP filters.
1790 char *binary_string_rfc2254(char *buf, int len)
1794 const char *hex = "0123456789ABCDEF";
1795 s = (char *)SMB_MALLOC(len * 3 + 1);
1798 for (j=i=0;i<len;i++) {
1800 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1801 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1808 char *binary_string(char *buf, int len)
1812 const char *hex = "0123456789ABCDEF";
1813 s = (char *)SMB_MALLOC(len * 2 + 1);
1816 for (j=i=0;i<len;i++) {
1817 s[j] = hex[((unsigned char)buf[i]) >> 4];
1818 s[j+1] = hex[((unsigned char)buf[i]) & 0xF];
1826 Just a typesafety wrapper for snprintf into a fstring.
1829 int fstr_sprintf(fstring s, const char *fmt, ...)
1835 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1841 List of Strings manipulation functions
1844 #define S_LIST_ABS 16 /* List Allocation Block Size */
1847 * Return true if all the elements of the list match exactly.
1849 bool str_list_compare(char **list1, char **list2)
1853 if (!list1 || !list2)
1854 return (list1 == list2);
1856 for (num = 0; list1[num]; num++) {
1859 if (!strcsequal(list1[num], list2[num]))
1863 return false; /* if list2 has more elements than list1 fail */
1869 /******************************************************************************
1870 version of standard_sub_basic() for string lists; uses talloc_sub_basic()
1872 *****************************************************************************/
1874 bool str_list_sub_basic( char **list, const char *smb_name,
1875 const char *domain_name )
1877 TALLOC_CTX *ctx = list;
1882 tmpstr = talloc_sub_basic(ctx, smb_name, domain_name, s);
1884 DEBUG(0,("str_list_sub_basic: "
1885 "alloc_sub_basic() return NULL!\n"));
1898 /******************************************************************************
1899 substritute a specific pattern in a string list
1900 *****************************************************************************/
1902 bool str_list_substitute(char **list, const char *pattern, const char *insert)
1904 TALLOC_CTX *ctx = list;
1906 ssize_t ls, lp, li, ld, i, d;
1915 lp = (ssize_t)strlen(pattern);
1916 li = (ssize_t)strlen(insert);
1921 ls = (ssize_t)strlen(s);
1923 while ((p = strstr_m(s, pattern))) {
1927 t = TALLOC_ARRAY(ctx, char, ls +ld +1);
1929 DEBUG(0,("str_list_substitute: "
1930 "Unable to allocate memory"));
1933 memcpy(t, *list, d);
1934 memcpy(t +d +li, p +lp, ls -d -lp +1);
1941 for (i = 0; i < li; i++) {
1942 switch (insert[i]) {
1954 t[d +i] = insert[i];
1966 #define IPSTR_LIST_SEP ","
1967 #define IPSTR_LIST_CHAR ','
1970 * Add ip string representation to ipstr list. Used also
1971 * as part of @function ipstr_list_make
1973 * @param ipstr_list pointer to string containing ip list;
1974 * MUST BE already allocated and IS reallocated if necessary
1975 * @param ipstr_size pointer to current size of ipstr_list (might be changed
1976 * as a result of reallocation)
1977 * @param ip IP address which is to be added to list
1978 * @return pointer to string appended with new ip and possibly
1979 * reallocated to new length
1982 static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service)
1984 char *new_ipstr = NULL;
1985 char addr_buf[INET6_ADDRSTRLEN];
1988 /* arguments checking */
1989 if (!ipstr_list || !service) {
1993 print_sockaddr(addr_buf,
1997 /* attempt to convert ip to a string and append colon separator to it */
1999 if (service->ss.ss_family == AF_INET) {
2001 ret = asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list,
2002 IPSTR_LIST_SEP, addr_buf,
2006 ret = asprintf(&new_ipstr, "%s%s[%s]:%d", *ipstr_list,
2007 IPSTR_LIST_SEP, addr_buf,
2010 SAFE_FREE(*ipstr_list);
2012 if (service->ss.ss_family == AF_INET) {
2014 ret = asprintf(&new_ipstr, "%s:%d", addr_buf,
2018 ret = asprintf(&new_ipstr, "[%s]:%d", addr_buf,
2025 *ipstr_list = new_ipstr;
2030 * Allocate and initialise an ipstr list using ip adresses
2031 * passed as arguments.
2033 * @param ipstr_list pointer to string meant to be allocated and set
2034 * @param ip_list array of ip addresses to place in the list
2035 * @param ip_count number of addresses stored in ip_list
2036 * @return pointer to allocated ip string
2039 char *ipstr_list_make(char **ipstr_list,
2040 const struct ip_service *ip_list,
2045 /* arguments checking */
2046 if (!ip_list || !ipstr_list) {
2052 /* process ip addresses given as arguments */
2053 for (i = 0; i < ip_count; i++) {
2054 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
2057 return (*ipstr_list);
2062 * Parse given ip string list into array of ip addresses
2063 * (as ip_service structures)
2064 * e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
2066 * @param ipstr ip string list to be parsed
2067 * @param ip_list pointer to array of ip addresses which is
2068 * allocated by this function and must be freed by caller
2069 * @return number of successfully parsed addresses
2072 int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list)
2075 char *token_str = NULL;
2079 if (!ipstr_list || !ip_list)
2082 count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
2083 if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
2084 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n",
2085 (unsigned long)count));
2089 frame = talloc_stackframe();
2090 for ( i=0; next_token_talloc(frame, &ipstr_list, &token_str,
2091 IPSTR_LIST_SEP) && i<count; i++ ) {
2092 char *s = token_str;
2093 char *p = strrchr(token_str, ':');
2097 (*ip_list)[i].port = atoi(p+1);
2100 /* convert single token to ip address */
2101 if (token_str[0] == '[') {
2104 p = strchr(token_str, ']');
2110 if (!interpret_string_addr(&(*ip_list)[i].ss,
2121 * Safely free ip string list
2123 * @param ipstr_list ip string list to be freed
2126 void ipstr_list_free(char* ipstr_list)
2128 SAFE_FREE(ipstr_list);
2132 Unescape a URL encoded string, in place.
2135 void rfc1738_unescape(char *buf)
2139 while (p && *p && (p=strchr_m(p,'%'))) {
2143 if (c1 >= '0' && c1 <= '9')
2145 else if (c1 >= 'A' && c1 <= 'F')
2147 else if (c1 >= 'a' && c1 <= 'f')
2149 else {p++; continue;}
2151 if (c2 >= '0' && c2 <= '9')
2153 else if (c2 >= 'A' && c2 <= 'F')
2155 else if (c2 >= 'a' && c2 <= 'f')
2157 else {p++; continue;}
2161 memmove(p+1, p+3, strlen(p+3)+1);
2166 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2169 * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
2171 DATA_BLOB base64_decode_data_blob(const char *s)
2173 int bit_offset, byte_offset, idx, i, n;
2174 DATA_BLOB decoded = data_blob(s, strlen(s)+1);
2175 unsigned char *d = decoded.data;
2180 while (*s && (p=strchr_m(b64,*s))) {
2181 idx = (int)(p - b64);
2182 byte_offset = (i*6)/8;
2183 bit_offset = (i*6)%8;
2184 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
2185 if (bit_offset < 3) {
2186 d[byte_offset] |= (idx << (2-bit_offset));
2189 d[byte_offset] |= (idx >> (bit_offset-2));
2190 d[byte_offset+1] = 0;
2191 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
2197 if ((n > 0) && (*s == '=')) {
2207 * Decode a base64 string in-place - wrapper for the above
2209 void base64_decode_inplace(char *s)
2211 DATA_BLOB decoded = base64_decode_data_blob(s);
2213 if ( decoded.length != 0 ) {
2214 memcpy(s, decoded.data, decoded.length);
2216 /* null terminate */
2217 s[decoded.length] = '\0';
2222 data_blob_free(&decoded);
2226 * Encode a base64 string into a talloc()ed string caller to free.
2228 * From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c
2232 char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
2236 size_t out_cnt, len, output_len;
2239 if (!data.length || !data.data)
2244 output_len = data.length * 2 + 4; /* Account for closing bytes. 4 is
2245 * random but should be enough for
2247 result = TALLOC_ARRAY(mem_ctx, char, output_len); /* get us plenty of space */
2248 SMB_ASSERT(result != NULL);
2250 while (len-- && out_cnt < (data.length * 2) - 5) {
2251 int c = (unsigned char) *(data.data++);
2254 if (char_count == 3) {
2255 result[out_cnt++] = b64[bits >> 18];
2256 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2257 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2258 result[out_cnt++] = b64[bits & 0x3f];
2265 if (char_count != 0) {
2266 bits <<= 16 - (8 * char_count);
2267 result[out_cnt++] = b64[bits >> 18];
2268 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2269 if (char_count == 1) {
2270 result[out_cnt++] = '=';
2271 result[out_cnt++] = '=';
2273 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2274 result[out_cnt++] = '=';
2277 result[out_cnt] = '\0'; /* terminate */
2281 /* read a SMB_BIG_UINT from a string */
2282 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
2285 SMB_BIG_UINT val = -1;
2286 const char *p = nptr;
2295 while (*p && isspace(*p))
2298 #ifdef LARGE_SMB_OFF_T
2299 sscanf(p,"%llu",&val);
2300 #else /* LARGE_SMB_OFF_T */
2301 sscanf(p,"%lu",&val);
2302 #endif /* LARGE_SMB_OFF_T */
2304 while (*p && isdigit(*p))
2312 /* Convert a size specification to a count of bytes. We accept the following
2314 * bytes if there is no suffix
2319 * pP whatever the ISO name for petabytes is
2321 * Returns 0 if the string can't be converted.
2323 SMB_OFF_T conv_str_size(const char * str)
2328 if (str == NULL || *str == '\0') {
2332 #ifdef HAVE_STRTOULL
2333 if (sizeof(SMB_OFF_T) == 8) {
2334 lval = strtoull(str, &end, 10 /* base */);
2336 lval = strtoul(str, &end, 10 /* base */);
2339 lval = strtoul(str, &end, 10 /* base */);
2342 if (end == NULL || end == str) {
2347 SMB_OFF_T lval_orig = lval;
2349 if (strwicmp(end, "K") == 0) {
2350 lval *= (SMB_OFF_T)1024;
2351 } else if (strwicmp(end, "M") == 0) {
2352 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2353 } else if (strwicmp(end, "G") == 0) {
2354 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2356 } else if (strwicmp(end, "T") == 0) {
2357 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2358 (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2359 } else if (strwicmp(end, "P") == 0) {
2360 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2361 (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2367 /* Primitive attempt to detect wrapping on platforms with
2368 * 4-byte SMB_OFF_T. It's better to let the caller handle
2369 * a failure than some random number.
2371 if (lval_orig <= lval) {
2379 void string_append(char **left, const char *right)
2381 int new_len = strlen(right) + 1;
2383 if (*left == NULL) {
2384 *left = (char *)SMB_MALLOC(new_len);
2387 new_len += strlen(*left);
2388 *left = (char *)SMB_REALLOC(*left, new_len);
2391 if (*left == NULL) {
2395 safe_strcat(*left, right, new_len-1);
2398 bool add_string_to_array(TALLOC_CTX *mem_ctx,
2399 const char *str, const char ***strings,
2402 char *dup_str = talloc_strdup(mem_ctx, str);
2404 *strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings,
2405 const char *, (*num)+1);
2407 if ((*strings == NULL) || (dup_str == NULL)) {
2412 (*strings)[*num] = dup_str;
2417 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
2418 * error checking in between. The indiation that something weird happened is
2421 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
2422 size_t *bufsize, const char *fmt, ...)
2429 /* len<0 is an internal marker that something failed */
2433 if (*string == NULL) {
2437 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
2438 if (*string == NULL)
2443 ret = vasprintf(&newstr, fmt, ap);
2451 while ((*len)+ret >= *bufsize) {
2454 if (*bufsize >= (1024*1024*256))
2459 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
2461 if (*string == NULL) {
2466 StrnCpy((*string)+(*len), newstr, ret);
2477 * asprintf into a string and strupper_m it after that.
2480 int asprintf_strupper_m(char **strp, const char *fmt, ...)
2487 ret = vasprintf(&result, fmt, ap);
2498 char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
2504 ret = talloc_vasprintf(t, fmt, ap);
2514 char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
2520 ret = talloc_vasprintf(t, fmt, ap);
2532 Returns the substring from src between the first occurrence of
2533 the char "front" and the first occurence of the char "back".
2534 Mallocs the return string which must be freed. Not for use
2535 with wide character strings.
2537 char *sstring_sub(const char *src, char front, char back)
2539 char *temp1, *temp2, *temp3;
2542 temp1 = strchr(src, front);
2543 if (temp1 == NULL) return NULL;
2544 temp2 = strchr(src, back);
2545 if (temp2 == NULL) return NULL;
2546 len = temp2 - temp1;
2547 if (len <= 0) return NULL;
2548 temp3 = (char*)SMB_MALLOC(len);
2549 if (temp3 == NULL) {
2550 DEBUG(1,("Malloc failure in sstring_sub\n"));
2553 memcpy(temp3, temp1+1, len-1);
2554 temp3[len-1] = '\0';
2558 /********************************************************************
2559 Check a string for any occurrences of a specified list of invalid
2561 ********************************************************************/
2563 bool validate_net_name( const char *name,
2564 const char *invalid_chars,
2569 for ( i=0; i<max_len && name[i]; i++ ) {
2570 /* fail if strchr_m() finds one of the invalid characters */
2571 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
2581 return the number of bytes occupied by a buffer in ASCII format
2582 the result includes the null termination
2583 limited by 'n' bytes
2585 size_t ascii_len_n(const char *src, size_t n)
2589 len = strnlen(src, n);
2598 return the number of bytes occupied by a buffer in CH_UTF16 format
2599 the result includes the null termination
2601 size_t utf16_len(const void *buf)
2605 for (len = 0; SVAL(buf,len); len += 2) ;
2611 return the number of bytes occupied by a buffer in CH_UTF16 format
2612 the result includes the null termination
2613 limited by 'n' bytes
2615 size_t utf16_len_n(const void *src, size_t n)
2619 for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
2628 /*******************************************************************
2629 Add a shell escape character '\' to any character not in a known list
2630 of characters. UNIX charset format.
2631 *******************************************************************/
2633 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
2634 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
2636 char *escape_shell_string(const char *src)
2638 size_t srclen = strlen(src);
2639 char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
2641 bool in_s_quote = false;
2642 bool in_d_quote = false;
2643 bool next_escaped = false;
2651 codepoint_t c = next_codepoint(src, &c_size);
2653 if (c == INVALID_CODEPOINT) {
2659 memcpy(dest, src, c_size);
2662 next_escaped = false;
2667 * Deal with backslash escaped state.
2668 * This only lasts for one character.
2673 next_escaped = false;
2678 * Deal with single quote state. The
2679 * only thing we care about is exiting
2692 * Deal with double quote state. The most
2693 * complex state. We must cope with \, meaning
2694 * possibly escape next char (depending what it
2695 * is), ", meaning exit this state, and possibly
2696 * add an \ escape to any unprotected character
2697 * (listed in INSIDE_DQUOTE_LIST).
2703 * Next character might be escaped.
2704 * We have to peek. Inside double
2705 * quotes only INSIDE_DQUOTE_LIST
2706 * characters are escaped by a \.
2711 c = next_codepoint(&src[1], &c_size);
2712 if (c == INVALID_CODEPOINT) {
2718 * Don't escape the next char.
2727 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
2729 next_escaped = true;
2736 /* Exit double quote state. */
2743 * We know the character isn't \ or ",
2744 * so escape it if it's any of the other
2745 * possible unprotected characters.
2748 if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
2756 * From here to the end of the loop we're
2757 * not in the single or double quote state.
2761 /* Next character must be escaped. */
2762 next_escaped = true;
2768 /* Go into single quote state. */
2775 /* Go into double quote state. */
2781 /* Check if we need to escape the character. */
2783 if (!strchr(INCLUDE_LIST, (int)*src)) {