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/>.
29 * @brief String utilities.
32 static bool next_token_internal_talloc(TALLOC_CTX *ctx,
51 /* default to simple separators */
56 /* find the first non sep char, if left-trimming is requested */
58 while (*s && strchr_m(sep,*s)) {
68 /* When restarting we need to go from here. */
71 /* Work out the length needed. */
72 for (quoted = false; *s &&
73 (quoted || !strchr_m(sep,*s)); s++) {
81 /* We started with len = 1 so we have space for the nul. */
82 *pp_buff = TALLOC_ARRAY(ctx, char, len);
87 /* copy over the token */
90 for (quoted = false; *s &&
91 (quoted || !strchr_m(sep,*s)); s++) {
99 *ptr = (*s) ? s+1 : s;
107 * Get the next token from a string, return false if none found. Handles
108 * double-quotes. This version trims leading separator characters before
109 * looking for a token.
111 bool next_token(const char **ptr, char *buff, const char *sep, size_t bufsize)
113 return next_token_internal(ptr, buff, sep, bufsize, true);
117 bool next_token_talloc(TALLOC_CTX *ctx,
122 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
126 * Get the next token from a string, return false if none found. Handles
127 * double-quotes. This version does not trim leading separator characters
128 * before looking for a token.
131 bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
136 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
140 * Case insensitive string compararison.
142 * iconv does not directly give us a way to compare strings in
143 * arbitrary unix character sets -- all we can is convert and then
144 * compare. This is expensive.
146 * As an optimization, we do a first pass that considers only the
147 * prefix of the strings that is entirely 7-bit. Within this, we
148 * check whether they have the same value.
150 * Hopefully this will often give the answer without needing to copy.
151 * In particular it should speed comparisons to literal ascii strings
152 * or comparisons of strings that are "obviously" different.
154 * If we find a non-ascii character we fall back to converting via
157 * This should never be slower than convering the whole thing, and
160 * A different optimization would be to compare for bitwise equality
161 * in the binary encoding. (It would be possible thought hairy to do
162 * both simultaneously.) But in that case if they turn out to be
163 * different, we'd need to restart the whole thing.
165 * Even better is to implement strcasecmp for each encoding and use a
168 int StrCaseCmp(const char *s, const char *t)
173 smb_ucs2_t *buffer_s, *buffer_t;
176 for (ps = s, pt = t; ; ps++, pt++) {
180 return 0; /* both ended */
182 return -1; /* s is a prefix */
184 return +1; /* t is a prefix */
185 else if ((*ps & 0x80) || (*pt & 0x80))
186 /* not ascii anymore, do it the hard way
190 us = toupper_ascii(*ps);
191 ut = toupper_ascii(*pt);
200 size = push_ucs2_allocate(&buffer_s, ps);
201 if (size == (size_t)-1) {
202 return strcmp(ps, pt);
203 /* Not quite the right answer, but finding the right one
204 under this failure case is expensive, and it's pretty
208 size = push_ucs2_allocate(&buffer_t, pt);
209 if (size == (size_t)-1) {
211 return strcmp(ps, pt);
212 /* Not quite the right answer, but finding the right one
213 under this failure case is expensive, and it's pretty
217 ret = strcasecmp_w(buffer_s, buffer_t);
225 Case insensitive string compararison, length limited.
227 int StrnCaseCmp(const char *s, const char *t, size_t len)
232 smb_ucs2_t *buffer_s, *buffer_t;
235 for (ps = s, pt = t; n < len ; ps++, pt++, n++) {
239 return 0; /* both ended */
241 return -1; /* s is a prefix */
243 return +1; /* t is a prefix */
244 else if ((*ps & 0x80) || (*pt & 0x80))
245 /* not ascii anymore, do it the
246 * hard way from here on in */
249 us = toupper_ascii(*ps);
250 ut = toupper_ascii(*pt);
263 size = push_ucs2_allocate(&buffer_s, ps);
264 if (size == (size_t)-1) {
265 return strncmp(ps, pt, len-n);
266 /* Not quite the right answer, but finding the right one
267 under this failure case is expensive,
268 and it's pretty close */
271 size = push_ucs2_allocate(&buffer_t, pt);
272 if (size == (size_t)-1) {
274 return strncmp(ps, pt, len-n);
275 /* Not quite the right answer, but finding the right one
276 under this failure case is expensive,
277 and it's pretty close */
280 ret = strncasecmp_w(buffer_s, buffer_t, len-n);
289 * @note The comparison is case-insensitive.
291 bool strequal(const char *s1, const char *s2)
298 return(StrCaseCmp(s1,s2)==0);
302 * Compare 2 strings up to and including the nth char.
304 * @note The comparison is case-insensitive.
306 bool strnequal(const char *s1,const char *s2,size_t n)
310 if (!s1 || !s2 || !n)
313 return(StrnCaseCmp(s1,s2,n)==0);
317 Compare 2 strings (case sensitive).
320 bool strcsequal(const char *s1,const char *s2)
327 return(strcmp(s1,s2)==0);
331 Do a case-insensitive, whitespace-ignoring string compare.
334 int strwicmp(const char *psz1, const char *psz2)
336 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
337 /* appropriate value. */
340 else if (psz1 == NULL)
342 else if (psz2 == NULL)
345 /* sync the strings on first non-whitespace */
347 while (isspace((int)*psz1))
349 while (isspace((int)*psz2))
351 if (toupper_ascii(*psz1) != toupper_ascii(*psz2) ||
352 *psz1 == '\0' || *psz2 == '\0')
357 return (*psz1 - *psz2);
361 Convert a string to "normal" form.
364 void strnorm(char *s, int case_default)
366 if (case_default == CASE_UPPER)
373 Check if a string is in "normal" case.
376 bool strisnormal(const char *s, int case_default)
378 if (case_default == CASE_UPPER)
379 return(!strhaslower(s));
381 return(!strhasupper(s));
387 NOTE: oldc and newc must be 7 bit characters
389 void string_replace( char *s, char oldc, char newc )
393 /* this is quite a common operation, so we want it to be
394 fast. We optimise for the ascii case, knowing that all our
395 supported multi-byte character sets are ascii-compatible
396 (ie. they match for the first 128 chars) */
398 for (p = s; *p; p++) {
399 if (*p & 0x80) /* mb string - slow path. */
409 /* Slow (mb) path. */
410 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
411 /* With compose characters we must restart from the beginning. JRA. */
417 next_codepoint(p, &c_size);
429 * Skip past some strings in a buffer - old version - no checks.
432 char *push_skip_string(char *buf)
434 buf += strlen(buf) + 1;
439 Skip past a string in a buffer. Buffer may not be
440 null terminated. end_ptr points to the first byte after
441 then end of the buffer.
444 char *skip_string(const char *base, size_t len, char *buf)
446 const char *end_ptr = base + len;
448 if (end_ptr < base || !base || !buf || buf >= end_ptr) {
452 /* Skip the string */
455 if (buf >= end_ptr) {
465 Count the number of characters in a string. Normally this will
466 be the same as the number of bytes in a string for single byte strings,
467 but will be different for multibyte.
470 size_t str_charnum(const char *s)
473 smb_ucs2_t *tmpbuf2 = NULL;
474 if (push_ucs2_allocate(&tmpbuf2, s) == (size_t)-1) {
477 ret = strlen_w(tmpbuf2);
483 Count the number of characters in a string. Normally this will
484 be the same as the number of bytes in a string for single byte strings,
485 but will be different for multibyte.
488 size_t str_ascii_charnum(const char *s)
491 char *tmpbuf2 = NULL;
492 if (push_ascii_allocate(&tmpbuf2, s) == (size_t)-1) {
495 ret = strlen(tmpbuf2);
500 bool trim_char(char *s,char cfront,char cback)
506 /* Ignore null or empty strings. */
507 if (!s || (s[0] == '\0'))
511 while (*fp && *fp == cfront)
514 /* We ate the string. */
522 ep = fp + strlen(fp) - 1;
524 /* Attempt ascii only. Bail for mb strings. */
525 while ((ep >= fp) && (*ep == cback)) {
527 if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
528 /* Could be mb... bail back to tim_string. */
536 return trim_string(s, cfront ? fs : NULL, bs);
542 /* We ate the string. */
549 memmove(s, fp, ep-fp+2);
554 Trim the specified elements off the front and back of a string.
557 bool trim_string(char *s,const char *front,const char *back)
564 /* Ignore null or empty strings. */
565 if (!s || (s[0] == '\0'))
568 front_len = front? strlen(front) : 0;
569 back_len = back? strlen(back) : 0;
574 while (len && strncmp(s, front, front_len)==0) {
575 /* Must use memmove here as src & dest can
576 * easily overlap. Found by valgrind. JRA. */
577 memmove(s, s+front_len, (len-front_len)+1);
584 while ((len >= back_len) &&
585 strncmp(s+len-back_len,back,back_len)==0) {
586 s[len-back_len]='\0';
595 Does a string have any uppercase chars in it?
598 bool strhasupper(const char *s)
603 if (push_ucs2_allocate(&tmp, s) == -1) {
607 for(p = tmp; *p != 0; p++) {
619 Does a string have any lowercase chars in it?
622 bool strhaslower(const char *s)
627 if (push_ucs2_allocate(&tmp, s) == -1) {
631 for(p = tmp; *p != 0; p++) {
643 Find the number of 'c' chars in a string
646 size_t count_chars(const char *s,char c)
650 smb_ucs2_t *alloc_tmpbuf = NULL;
652 if (push_ucs2_allocate(&alloc_tmpbuf, s) == (size_t)-1) {
656 for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++)
657 if(*ptr==UCS2_CHAR(c))
660 SAFE_FREE(alloc_tmpbuf);
665 Safe string copy into a known length string. maxlength does not
666 include the terminating zero.
669 char *safe_strcpy_fn(const char *fn,
678 DEBUG(0,("ERROR: NULL dest in safe_strcpy, "
679 "called from [%s][%d]\n", fn, line));
684 clobber_region(fn,line,dest, maxlength+1);
692 len = strnlen(src, maxlength+1);
694 if (len > maxlength) {
695 DEBUG(0,("ERROR: string overflow by "
696 "%lu (%lu - %lu) in safe_strcpy [%.50s]\n",
697 (unsigned long)(len-maxlength), (unsigned long)len,
698 (unsigned long)maxlength, src));
702 memmove(dest, src, len);
708 Safe string cat into a string. maxlength does not
709 include the terminating zero.
711 char *safe_strcat_fn(const char *fn,
717 size_t src_len, dest_len;
720 DEBUG(0,("ERROR: NULL dest in safe_strcat, "
721 "called from [%s][%d]\n", fn, line));
728 src_len = strnlen(src, maxlength + 1);
729 dest_len = strnlen(dest, maxlength + 1);
732 clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
735 if (src_len + dest_len > maxlength) {
736 DEBUG(0,("ERROR: string overflow by %d "
737 "in safe_strcat [%.50s]\n",
738 (int)(src_len + dest_len - maxlength), src));
739 if (maxlength > dest_len) {
740 memcpy(&dest[dest_len], src, maxlength - dest_len);
746 memcpy(&dest[dest_len], src, src_len);
747 dest[dest_len + src_len] = 0;
752 Paranoid strcpy into a buffer of given length (includes terminating
753 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
754 and replaces with '_'. Deliberately does *NOT* check for multibyte
755 characters. Don't change it !
758 char *alpha_strcpy_fn(const char *fn,
762 const char *other_safe_chars,
768 clobber_region(fn, line, dest, maxlength);
772 DEBUG(0,("ERROR: NULL dest in alpha_strcpy, "
773 "called from [%s][%d]\n", fn, line));
783 if (len >= maxlength)
786 if (!other_safe_chars)
787 other_safe_chars = "";
789 for(i = 0; i < len; i++) {
790 int val = (src[i] & 0xff);
791 if (isupper_ascii(val) || islower_ascii(val) ||
792 isdigit(val) || strchr_m(other_safe_chars, val))
804 Like strncpy but always null terminates. Make sure there is room!
805 The variable n should always be one less than the available size.
807 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
812 clobber_region(fn, line, dest, n+1);
816 DEBUG(0,("ERROR: NULL dest in StrnCpy, "
817 "called from [%s][%d]\n", fn, line));
826 while (n-- && (*d = *src)) {
837 Like strncpy but copies up to the character marker. always null terminates.
838 returns a pointer to the character marker in the source string (src).
841 static char *strncpyn(char *dest, const char *src, size_t n, char c)
847 clobber_region(dest, n+1);
849 p = strchr_m(src, c);
851 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
855 str_len = PTR_DIFF(p, src);
856 strncpy(dest, src, MIN(n, str_len));
857 dest[str_len] = '\0';
864 Routine to get hex characters and turn them into a 16 byte array.
865 the array can be variable length, and any non-hex-numeric
866 characters are skipped. "0xnn" or "0Xnn" is specially catered
869 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
873 size_t strhex_to_str(char *buf, size_t buf_len, const char *strhex, size_t strhex_len)
876 size_t num_chars = 0;
877 unsigned char lonybble, hinybble;
878 const char *hexchars = "0123456789ABCDEF";
879 char *p1 = NULL, *p2 = NULL;
881 for (i = 0; i < strhex_len && strhex[i] != 0; i++) {
882 if (strnequal(hexchars, "0x", 2)) {
883 i++; /* skip two chars */
887 if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
890 i++; /* next hex digit */
892 if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
895 /* get the two nybbles */
896 hinybble = PTR_DIFF(p1, hexchars);
897 lonybble = PTR_DIFF(p2, hexchars);
899 if (num_chars >= buf_len) {
902 buf[num_chars] = (hinybble << 4) | lonybble;
911 DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
916 ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
918 ret_blob = data_blob(NULL, strlen(strhex)/2+1);
920 ret_blob.length = strhex_to_str((char*)ret_blob.data,
929 * Routine to print a buffer as HEX digits, into an allocated string.
932 char *hex_encode(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
937 hex_buffer = TALLOC_ARRAY(mem_ctx, char, (len*2)+1);
939 for (i = 0; i < len; i++)
940 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
946 Check if a string is part of a list.
949 bool in_list(const char *s, const char *list, bool casesensitive)
959 frame = talloc_stackframe();
960 while (next_token_talloc(frame, &list, &tok,LIST_SEP)) {
962 if (strcmp(tok,s) == 0) {
967 if (StrCaseCmp(tok,s) == 0) {
977 /* this is used to prevent lots of mallocs of size 1 */
978 static const char null_string[] = "";
981 Set a string value, allocing the space for the string
984 static bool string_init(char **dest,const char *src)
994 *dest = CONST_DISCARD(char*, null_string);
996 (*dest) = SMB_STRDUP(src);
997 if ((*dest) == NULL) {
998 DEBUG(0,("Out of memory in string_init\n"));
1006 Free a string value.
1009 void string_free(char **s)
1013 if (*s == null_string)
1019 Set a string value, deallocating any existing space, and allocing the space
1023 bool string_set(char **dest,const char *src)
1026 return(string_init(dest,src));
1030 Substitute a string for a pattern in another string. Make sure there is
1033 This routine looks for pattern in s and replaces it with
1034 insert. It may do multiple replacements or just one.
1036 Any of " ; ' $ or ` in the insert string are replaced with _
1037 if len==0 then the string cannot be extended. This is different from the old
1038 use of len==0 which was for no length checks to be done.
1041 void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
1042 bool remove_unsafe_characters, bool replace_once,
1043 bool allow_trailing_dollar)
1046 ssize_t ls,lp,li, i;
1048 if (!insert || !pattern || !*pattern || !s)
1051 ls = (ssize_t)strlen(s);
1052 lp = (ssize_t)strlen(pattern);
1053 li = (ssize_t)strlen(insert);
1056 len = ls + 1; /* len is number of *bytes* */
1058 while (lp <= ls && (p = strstr_m(s,pattern))) {
1059 if (ls + (li-lp) >= len) {
1060 DEBUG(0,("ERROR: string overflow by "
1061 "%d in string_sub(%.50s, %d)\n",
1062 (int)(ls + (li-lp) - len),
1063 pattern, (int)len));
1067 memmove(p+li,p+lp,strlen(p+lp)+1);
1069 for (i=0;i<li;i++) {
1070 switch (insert[i]) {
1076 /* allow a trailing $
1077 * (as in machine accounts) */
1078 if (allow_trailing_dollar && (i == li - 1 )) {
1085 if ( remove_unsafe_characters ) {
1087 /* yes this break should be here
1088 * since we want to fall throw if
1089 * not replacing unsafe chars */
1104 void string_sub_once(char *s, const char *pattern,
1105 const char *insert, size_t len)
1107 string_sub2( s, pattern, insert, len, true, true, false );
1110 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
1112 string_sub2( s, pattern, insert, len, true, false, false );
1115 void fstring_sub(char *s,const char *pattern,const char *insert)
1117 string_sub(s, pattern, insert, sizeof(fstring));
1121 Similar to string_sub2, but it will accept only allocated strings
1122 and may realloc them so pay attention at what you pass on no
1123 pointers inside strings, no const may be passed
1127 char *realloc_string_sub2(char *string,
1128 const char *pattern,
1130 bool remove_unsafe_characters,
1131 bool allow_trailing_dollar)
1135 ssize_t ls,lp,li,ld, i;
1137 if (!insert || !pattern || !*pattern || !string || !*string)
1142 in = SMB_STRDUP(insert);
1144 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1147 ls = (ssize_t)strlen(s);
1148 lp = (ssize_t)strlen(pattern);
1149 li = (ssize_t)strlen(insert);
1151 for (i=0;i<li;i++) {
1158 /* allow a trailing $
1159 * (as in machine accounts) */
1160 if (allow_trailing_dollar && (i == li - 1 )) {
1166 if ( remove_unsafe_characters ) {
1176 while ((p = strstr_m(s,pattern))) {
1178 int offset = PTR_DIFF(s,string);
1179 string = (char *)SMB_REALLOC(string, ls + ld + 1);
1181 DEBUG(0, ("realloc_string_sub: "
1182 "out of memory!\n"));
1186 p = string + offset + (p - s);
1189 memmove(p+li,p+lp,strlen(p+lp)+1);
1199 char *realloc_string_sub(char *string,
1200 const char *pattern,
1203 return realloc_string_sub2(string, pattern, insert, true, false);
1207 * Internal guts of talloc_string_sub and talloc_all_string_sub.
1208 * talloc version of string_sub2.
1211 char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
1212 const char *pattern,
1214 bool remove_unsafe_characters,
1216 bool allow_trailing_dollar)
1221 ssize_t ls,lp,li,ld, i;
1223 if (!insert || !pattern || !*pattern || !src || !*src) {
1227 string = talloc_strdup(mem_ctx, src);
1228 if (string == NULL) {
1229 DEBUG(0, ("talloc_string_sub2: "
1230 "talloc_strdup failed\n"));
1236 in = SMB_STRDUP(insert);
1238 DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
1241 ls = (ssize_t)strlen(s);
1242 lp = (ssize_t)strlen(pattern);
1243 li = (ssize_t)strlen(insert);
1246 for (i=0;i<li;i++) {
1253 /* allow a trailing $
1254 * (as in machine accounts) */
1255 if (allow_trailing_dollar && (i == li - 1 )) {
1261 if (remove_unsafe_characters) {
1271 while ((p = strstr_m(s,pattern))) {
1273 int offset = PTR_DIFF(s,string);
1274 string = (char *)TALLOC_REALLOC(mem_ctx, string,
1277 DEBUG(0, ("talloc_string_sub: out of "
1282 p = string + offset + (p - s);
1285 memmove(p+li,p+lp,strlen(p+lp)+1);
1299 /* Same as string_sub, but returns a talloc'ed string */
1301 char *talloc_string_sub(TALLOC_CTX *mem_ctx,
1303 const char *pattern,
1306 return talloc_string_sub2(mem_ctx, src, pattern, insert,
1307 true, false, false);
1311 Similar to string_sub() but allows for any character to be substituted.
1313 if len==0 then the string cannot be extended. This is different from the old
1314 use of len==0 which was for no length checks to be done.
1317 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1322 if (!insert || !pattern || !s)
1325 ls = (ssize_t)strlen(s);
1326 lp = (ssize_t)strlen(pattern);
1327 li = (ssize_t)strlen(insert);
1333 len = ls + 1; /* len is number of *bytes* */
1335 while (lp <= ls && (p = strstr_m(s,pattern))) {
1336 if (ls + (li-lp) >= len) {
1337 DEBUG(0,("ERROR: string overflow by "
1338 "%d in all_string_sub(%.50s, %d)\n",
1339 (int)(ls + (li-lp) - len),
1340 pattern, (int)len));
1344 memmove(p+li,p+lp,strlen(p+lp)+1);
1346 memcpy(p, insert, li);
1352 char *talloc_all_string_sub(TALLOC_CTX *ctx,
1354 const char *pattern,
1357 return talloc_string_sub2(ctx, src, pattern, insert,
1358 false, false, false);
1362 Write an octal as a string.
1365 char *octal_string(int i)
1369 result = talloc_strdup(talloc_tos(), "-1");
1372 result = talloc_asprintf(talloc_tos(), "0%o", i);
1374 SMB_ASSERT(result != NULL);
1380 Truncate a string at a specified length.
1383 char *string_truncate(char *s, unsigned int length)
1385 if (s && strlen(s) > length)
1391 Strchr and strrchr_m are very hard to do on general multi-byte strings.
1392 We convert via ucs2 for now.
1395 char *strchr_m(const char *src, char c)
1397 smb_ucs2_t *ws = NULL;
1403 /* characters below 0x3F are guaranteed to not appear in
1404 non-initial position in multi-byte charsets */
1405 if ((c & 0xC0) == 0) {
1406 return strchr(src, c);
1409 /* this is quite a common operation, so we want it to be
1410 fast. We optimise for the ascii case, knowing that all our
1411 supported multi-byte character sets are ascii-compatible
1412 (ie. they match for the first 128 chars) */
1414 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1422 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1423 /* With compose characters we must restart from the beginning. JRA. */
1427 if (push_ucs2_allocate(&ws, s)==(size_t)-1) {
1428 /* Wrong answer, but what can we do... */
1429 return strchr(src, c);
1431 p = strchr_w(ws, UCS2_CHAR(c));
1437 if (pull_ucs2_allocate(&s2, ws)==(size_t)-1) {
1439 /* Wrong answer, but what can we do... */
1440 return strchr(src, c);
1442 ret = (char *)(s+strlen(s2));
1448 char *strrchr_m(const char *s, char c)
1450 /* characters below 0x3F are guaranteed to not appear in
1451 non-initial position in multi-byte charsets */
1452 if ((c & 0xC0) == 0) {
1453 return strrchr(s, c);
1456 /* this is quite a common operation, so we want it to be
1457 fast. We optimise for the ascii case, knowing that all our
1458 supported multi-byte character sets are ascii-compatible
1459 (ie. they match for the first 128 chars). Also, in Samba
1460 we only search for ascii characters in 'c' and that
1461 in all mb character sets with a compound character
1462 containing c, if 'c' is not a match at position
1463 p, then p[-1] > 0x7f. JRA. */
1466 size_t len = strlen(s);
1468 bool got_mb = false;
1475 /* Could be a match. Part of a multibyte ? */
1477 (((unsigned char)cp[-1]) & 0x80)) {
1478 /* Yep - go slow :-( */
1482 /* No - we have a match ! */
1485 } while (cp-- != s);
1490 /* String contained a non-ascii char. Slow path. */
1492 smb_ucs2_t *ws = NULL;
1497 if (push_ucs2_allocate(&ws,s)==(size_t)-1) {
1498 /* Wrong answer, but what can we do. */
1499 return strrchr(s, c);
1501 p = strrchr_w(ws, UCS2_CHAR(c));
1507 if (pull_ucs2_allocate(&s2,ws)==(size_t)-1) {
1509 /* Wrong answer, but what can we do. */
1510 return strrchr(s, c);
1512 ret = (char *)(s+strlen(s2));
1519 /***********************************************************************
1520 Return the equivalent of doing strrchr 'n' times - always going
1522 ***********************************************************************/
1524 char *strnrchr_m(const char *s, char c, unsigned int n)
1526 smb_ucs2_t *ws = NULL;
1531 if (push_ucs2_allocate(&ws,s)==(size_t)-1) {
1532 /* Too hard to try and get right. */
1535 p = strnrchr_w(ws, UCS2_CHAR(c), n);
1541 if (pull_ucs2_allocate(&s2,ws)==(size_t)-1) {
1543 /* Too hard to try and get right. */
1546 ret = (char *)(s+strlen(s2));
1552 /***********************************************************************
1553 strstr_m - We convert via ucs2 for now.
1554 ***********************************************************************/
1556 char *strstr_m(const char *src, const char *findstr)
1559 smb_ucs2_t *src_w, *find_w;
1564 size_t findstr_len = 0;
1566 /* for correctness */
1571 /* Samba does single character findstr calls a *lot*. */
1572 if (findstr[1] == '\0')
1573 return strchr_m(src, *findstr);
1575 /* We optimise for the ascii case, knowing that all our
1576 supported multi-byte character sets are ascii-compatible
1577 (ie. they match for the first 128 chars) */
1579 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1580 if (*s == *findstr) {
1582 findstr_len = strlen(findstr);
1584 if (strncmp(s, findstr, findstr_len) == 0) {
1593 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
1594 /* 'make check' fails unless we do this */
1596 /* With compose characters we must restart from the beginning. JRA. */
1600 if (push_ucs2_allocate(&src_w, src) == (size_t)-1) {
1601 DEBUG(0,("strstr_m: src malloc fail\n"));
1605 if (push_ucs2_allocate(&find_w, findstr) == (size_t)-1) {
1607 DEBUG(0,("strstr_m: find malloc fail\n"));
1611 p = strstr_w(src_w, find_w);
1620 if (pull_ucs2_allocate(&s2, src_w) == (size_t)-1) {
1623 DEBUG(0,("strstr_m: dest malloc fail\n"));
1626 retp = (char *)(s+strlen(s2));
1634 Convert a string to lower case.
1637 void strlower_m(char *s)
1642 /* this is quite a common operation, so we want it to be
1643 fast. We optimise for the ascii case, knowing that all our
1644 supported multi-byte character sets are ascii-compatible
1645 (ie. they match for the first 128 chars) */
1647 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1648 *s = tolower_ascii((unsigned char)*s);
1655 /* I assume that lowercased string takes the same number of bytes
1656 * as source string even in UTF-8 encoding. (VIV) */
1657 len = strlen(s) + 1;
1660 unix_strlower(s,len,s,len);
1661 /* Catch mb conversion errors that may not terminate. */
1668 Convert a string to upper case.
1671 void strupper_m(char *s)
1676 /* this is quite a common operation, so we want it to be
1677 fast. We optimise for the ascii case, knowing that all our
1678 supported multi-byte character sets are ascii-compatible
1679 (ie. they match for the first 128 chars) */
1681 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1682 *s = toupper_ascii((unsigned char)*s);
1689 /* I assume that lowercased string takes the same number of bytes
1690 * as source string even in multibyte encoding. (VIV) */
1691 len = strlen(s) + 1;
1694 unix_strupper(s,len,s,len);
1695 /* Catch mb conversion errors that may not terminate. */
1702 Count the number of UCS2 characters in a string. Normally this will
1703 be the same as the number of bytes in a string for single byte strings,
1704 but will be different for multibyte.
1707 size_t strlen_m(const char *s)
1715 while (*s && !(((uint8_t)*s) & 0x80)) {
1726 codepoint_t c = next_codepoint(s, &c_size);
1728 /* Unicode char fits into 16 bits. */
1731 /* Double-width unicode char - 32 bits. */
1741 Count the number of UCS2 characters in a string including the null
1745 size_t strlen_m_term(const char *s)
1750 return strlen_m(s) + 1;
1754 * Weird helper routine for the winreg pipe: If nothing is around, return 0,
1755 * if a string is there, include the terminator.
1758 size_t strlen_m_term_null(const char *s)
1772 Return a RFC2254 binary string representation of a buffer.
1773 Used in LDAP filters.
1777 char *binary_string_rfc2254(char *buf, int len)
1781 const char *hex = "0123456789ABCDEF";
1782 s = (char *)SMB_MALLOC(len * 3 + 1);
1785 for (j=i=0;i<len;i++) {
1787 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1788 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1795 char *binary_string(char *buf, int len)
1799 const char *hex = "0123456789ABCDEF";
1800 s = (char *)SMB_MALLOC(len * 2 + 1);
1803 for (j=i=0;i<len;i++) {
1804 s[j] = hex[((unsigned char)buf[i]) >> 4];
1805 s[j+1] = hex[((unsigned char)buf[i]) & 0xF];
1813 Just a typesafety wrapper for snprintf into a fstring.
1816 int fstr_sprintf(fstring s, const char *fmt, ...)
1822 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1828 List of Strings manipulation functions
1831 #define S_LIST_ABS 16 /* List Allocation Block Size */
1833 static char **str_list_make_internal(TALLOC_CTX *mem_ctx,
1837 char **list, **rlist;
1842 TALLOC_CTX *frame = NULL;
1844 if (!string || !*string)
1847 s = talloc_strdup(mem_ctx, string);
1849 s = SMB_STRDUP(string);
1852 DEBUG(0,("str_list_make: Unable to allocate memory"));
1855 if (!sep) sep = LIST_SEP;
1861 frame = talloc_stackframe();
1862 while (next_token_talloc(frame, &str, &tok, sep)) {
1864 lsize += S_LIST_ABS;
1866 rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list,
1869 /* We need to keep the old list on
1870 * error so we can free the elements
1871 if the realloc fails. */
1872 rlist =SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list,
1876 DEBUG(0,("str_list_make: "
1877 "Unable to allocate memory"));
1878 str_list_free(&list);
1889 memset (&list[num], 0,
1890 ((sizeof(char**)) * (S_LIST_ABS +1)));
1894 list[num] = talloc_strdup(mem_ctx, tok);
1896 list[num] = SMB_STRDUP(tok);
1900 DEBUG(0,("str_list_make: Unable to allocate memory"));
1901 str_list_free(&list);
1925 char **str_list_make_talloc(TALLOC_CTX *mem_ctx,
1929 return str_list_make_internal(mem_ctx, string, sep);
1932 char **str_list_make(const char *string, const char *sep)
1934 return str_list_make_internal(NULL, string, sep);
1937 bool str_list_copy(char ***dest, const char **src)
1939 char **list, **rlist;
1951 lsize += S_LIST_ABS;
1952 rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list,
1955 DEBUG(0,("str_list_copy: "
1956 "Unable to re-allocate memory"));
1957 str_list_free(&list);
1962 memset (&list[num], 0,
1963 ((sizeof(char **)) * (S_LIST_ABS +1)));
1966 list[num] = SMB_STRDUP(src[num]);
1968 DEBUG(0,("str_list_copy: Unable to allocate memory"));
1969 str_list_free(&list);
1981 * Return true if all the elements of the list match exactly.
1983 bool str_list_compare(char **list1, char **list2)
1987 if (!list1 || !list2)
1988 return (list1 == list2);
1990 for (num = 0; list1[num]; num++) {
1993 if (!strcsequal(list1[num], list2[num]))
1997 return false; /* if list2 has more elements than list1 fail */
2002 static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list)
2006 if (!list || !*list)
2009 for(; *tlist; tlist++) {
2011 TALLOC_FREE(*tlist);
2017 TALLOC_FREE(*tlist);
2023 void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list)
2025 str_list_free_internal(mem_ctx, list);
2028 void str_list_free(char ***list)
2030 str_list_free_internal(NULL, list);
2033 /******************************************************************************
2034 *****************************************************************************/
2036 int str_list_count( const char **list )
2043 /* count the number of list members */
2045 for ( i=0; *list; i++, list++ );
2050 /******************************************************************************
2051 version of standard_sub_basic() for string lists; uses alloc_sub_basic()
2053 *****************************************************************************/
2055 bool str_list_sub_basic( char **list, const char *smb_name,
2056 const char *domain_name )
2062 tmpstr = alloc_sub_basic(smb_name, domain_name, s);
2064 DEBUG(0,("str_list_sub_basic: "
2065 "alloc_sub_basic() return NULL!\n"));
2078 /******************************************************************************
2079 substritute a specific pattern in a string list
2080 *****************************************************************************/
2082 bool str_list_substitute(char **list, const char *pattern, const char *insert)
2085 ssize_t ls, lp, li, ld, i, d;
2094 lp = (ssize_t)strlen(pattern);
2095 li = (ssize_t)strlen(insert);
2100 ls = (ssize_t)strlen(s);
2102 while ((p = strstr_m(s, pattern))) {
2106 t = (char *) SMB_MALLOC(ls +ld +1);
2108 DEBUG(0,("str_list_substitute: "
2109 "Unable to allocate memory"));
2112 memcpy(t, *list, d);
2113 memcpy(t +d +li, p +lp, ls -d -lp +1);
2120 for (i = 0; i < li; i++) {
2121 switch (insert[i]) {
2133 t[d +i] = insert[i];
2145 #define IPSTR_LIST_SEP ","
2146 #define IPSTR_LIST_CHAR ','
2149 * Add ip string representation to ipstr list. Used also
2150 * as part of @function ipstr_list_make
2152 * @param ipstr_list pointer to string containing ip list;
2153 * MUST BE already allocated and IS reallocated if necessary
2154 * @param ipstr_size pointer to current size of ipstr_list (might be changed
2155 * as a result of reallocation)
2156 * @param ip IP address which is to be added to list
2157 * @return pointer to string appended with new ip and possibly
2158 * reallocated to new length
2161 static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service)
2163 char *new_ipstr = NULL;
2164 char addr_buf[INET6_ADDRSTRLEN];
2166 /* arguments checking */
2167 if (!ipstr_list || !service) {
2171 print_sockaddr(addr_buf,
2175 /* attempt to convert ip to a string and append colon separator to it */
2177 if (service->ss.ss_family == AF_INET) {
2179 asprintf(&new_ipstr, "%s%s%s:%d",
2186 asprintf(&new_ipstr, "%s%s[%s]:%d",
2192 SAFE_FREE(*ipstr_list);
2194 if (service->ss.ss_family == AF_INET) {
2196 asprintf(&new_ipstr, "%s:%d",
2201 asprintf(&new_ipstr, "[%s]:%d",
2206 *ipstr_list = new_ipstr;
2211 * Allocate and initialise an ipstr list using ip adresses
2212 * passed as arguments.
2214 * @param ipstr_list pointer to string meant to be allocated and set
2215 * @param ip_list array of ip addresses to place in the list
2216 * @param ip_count number of addresses stored in ip_list
2217 * @return pointer to allocated ip string
2220 char *ipstr_list_make(char **ipstr_list,
2221 const struct ip_service *ip_list,
2226 /* arguments checking */
2227 if (!ip_list || !ipstr_list) {
2233 /* process ip addresses given as arguments */
2234 for (i = 0; i < ip_count; i++) {
2235 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
2238 return (*ipstr_list);
2243 * Parse given ip string list into array of ip addresses
2244 * (as ip_service structures)
2245 * e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
2247 * @param ipstr ip string list to be parsed
2248 * @param ip_list pointer to array of ip addresses which is
2249 * allocated by this function and must be freed by caller
2250 * @return number of succesfully parsed addresses
2253 int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list)
2256 char *token_str = NULL;
2260 if (!ipstr_list || !ip_list)
2263 count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
2264 if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
2265 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n",
2266 (unsigned long)count));
2270 frame = talloc_stackframe();
2271 for ( i=0; next_token_talloc(frame, &ipstr_list, &token_str,
2272 IPSTR_LIST_SEP) && i<count; i++ ) {
2273 char *s = token_str;
2274 char *p = strrchr(token_str, ':');
2278 (*ip_list)[i].port = atoi(p+1);
2281 /* convert single token to ip address */
2282 if (token_str[0] == '[') {
2285 p = strchr(token_str, ']');
2291 if (!interpret_string_addr(&(*ip_list)[i].ss,
2302 * Safely free ip string list
2304 * @param ipstr_list ip string list to be freed
2307 void ipstr_list_free(char* ipstr_list)
2309 SAFE_FREE(ipstr_list);
2313 Unescape a URL encoded string, in place.
2316 void rfc1738_unescape(char *buf)
2320 while (p && *p && (p=strchr_m(p,'%'))) {
2324 if (c1 >= '0' && c1 <= '9')
2326 else if (c1 >= 'A' && c1 <= 'F')
2328 else if (c1 >= 'a' && c1 <= 'f')
2330 else {p++; continue;}
2332 if (c2 >= '0' && c2 <= '9')
2334 else if (c2 >= 'A' && c2 <= 'F')
2336 else if (c2 >= 'a' && c2 <= 'f')
2338 else {p++; continue;}
2342 memmove(p+1, p+3, strlen(p+3)+1);
2347 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2350 * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
2352 DATA_BLOB base64_decode_data_blob(const char *s)
2354 int bit_offset, byte_offset, idx, i, n;
2355 DATA_BLOB decoded = data_blob(s, strlen(s)+1);
2356 unsigned char *d = decoded.data;
2361 while (*s && (p=strchr_m(b64,*s))) {
2362 idx = (int)(p - b64);
2363 byte_offset = (i*6)/8;
2364 bit_offset = (i*6)%8;
2365 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
2366 if (bit_offset < 3) {
2367 d[byte_offset] |= (idx << (2-bit_offset));
2370 d[byte_offset] |= (idx >> (bit_offset-2));
2371 d[byte_offset+1] = 0;
2372 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
2378 if ((n > 0) && (*s == '=')) {
2388 * Decode a base64 string in-place - wrapper for the above
2390 void base64_decode_inplace(char *s)
2392 DATA_BLOB decoded = base64_decode_data_blob(s);
2394 if ( decoded.length != 0 ) {
2395 memcpy(s, decoded.data, decoded.length);
2397 /* null terminate */
2398 s[decoded.length] = '\0';
2403 data_blob_free(&decoded);
2407 * Encode a base64 string into a malloc()ed string caller to free.
2409 * From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c
2413 char *base64_encode_data_blob(DATA_BLOB data)
2417 size_t out_cnt, len, output_len;
2420 if (!data.length || !data.data)
2425 output_len = data.length * 2;
2426 result = TALLOC_ARRAY(talloc_tos(), char, output_len); /* get us plenty of space */
2427 SMB_ASSERT(result != NULL);
2429 while (len-- && out_cnt < (data.length * 2) - 5) {
2430 int c = (unsigned char) *(data.data++);
2433 if (char_count == 3) {
2434 result[out_cnt++] = b64[bits >> 18];
2435 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2436 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2437 result[out_cnt++] = b64[bits & 0x3f];
2444 if (char_count != 0) {
2445 bits <<= 16 - (8 * char_count);
2446 result[out_cnt++] = b64[bits >> 18];
2447 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2448 if (char_count == 1) {
2449 result[out_cnt++] = '=';
2450 result[out_cnt++] = '=';
2452 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2453 result[out_cnt++] = '=';
2456 result[out_cnt] = '\0'; /* terminate */
2460 /* read a SMB_BIG_UINT from a string */
2461 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
2464 SMB_BIG_UINT val = -1;
2465 const char *p = nptr;
2474 while (*p && isspace(*p))
2477 #ifdef LARGE_SMB_OFF_T
2478 sscanf(p,"%llu",&val);
2479 #else /* LARGE_SMB_OFF_T */
2480 sscanf(p,"%lu",&val);
2481 #endif /* LARGE_SMB_OFF_T */
2483 while (*p && isdigit(*p))
2491 /* Convert a size specification to a count of bytes. We accept the following
2493 * bytes if there is no suffix
2498 * pP whatever the ISO name for petabytes is
2500 * Returns 0 if the string can't be converted.
2502 SMB_OFF_T conv_str_size(const char * str)
2507 if (str == NULL || *str == '\0') {
2511 #ifdef HAVE_STRTOULL
2512 if (sizeof(SMB_OFF_T) == 8) {
2513 lval = strtoull(str, &end, 10 /* base */);
2515 lval = strtoul(str, &end, 10 /* base */);
2518 lval = strtoul(str, &end, 10 /* base */);
2521 if (end == NULL || end == str) {
2526 SMB_OFF_T lval_orig = lval;
2528 if (strwicmp(end, "K") == 0) {
2529 lval *= (SMB_OFF_T)1024;
2530 } else if (strwicmp(end, "M") == 0) {
2531 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2532 } else if (strwicmp(end, "G") == 0) {
2533 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2535 } else if (strwicmp(end, "T") == 0) {
2536 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2537 (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2538 } else if (strwicmp(end, "P") == 0) {
2539 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2540 (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2546 /* Primitive attempt to detect wrapping on platforms with
2547 * 4-byte SMB_OFF_T. It's better to let the caller handle
2548 * a failure than some random number.
2550 if (lval_orig <= lval) {
2558 void string_append(char **left, const char *right)
2560 int new_len = strlen(right) + 1;
2562 if (*left == NULL) {
2563 *left = (char *)SMB_MALLOC(new_len);
2566 new_len += strlen(*left);
2567 *left = (char *)SMB_REALLOC(*left, new_len);
2570 if (*left == NULL) {
2574 safe_strcat(*left, right, new_len-1);
2577 bool add_string_to_array(TALLOC_CTX *mem_ctx,
2578 const char *str, const char ***strings,
2581 char *dup_str = talloc_strdup(mem_ctx, str);
2583 *strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings,
2584 const char *, (*num)+1);
2586 if ((*strings == NULL) || (dup_str == NULL)) {
2591 (*strings)[*num] = dup_str;
2596 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
2597 * error checking in between. The indiation that something weird happened is
2600 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
2601 size_t *bufsize, const char *fmt, ...)
2608 /* len<0 is an internal marker that something failed */
2612 if (*string == NULL) {
2616 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
2617 if (*string == NULL)
2622 ret = vasprintf(&newstr, fmt, ap);
2630 while ((*len)+ret >= *bufsize) {
2633 if (*bufsize >= (1024*1024*256))
2638 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
2640 if (*string == NULL) {
2645 StrnCpy((*string)+(*len), newstr, ret);
2656 * asprintf into a string and strupper_m it after that.
2659 int asprintf_strupper_m(char **strp, const char *fmt, ...)
2666 ret = vasprintf(&result, fmt, ap);
2677 char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
2683 ret = talloc_vasprintf(t, fmt, ap);
2694 Returns the substring from src between the first occurrence of
2695 the char "front" and the first occurence of the char "back".
2696 Mallocs the return string which must be freed. Not for use
2697 with wide character strings.
2699 char *sstring_sub(const char *src, char front, char back)
2701 char *temp1, *temp2, *temp3;
2704 temp1 = strchr(src, front);
2705 if (temp1 == NULL) return NULL;
2706 temp2 = strchr(src, back);
2707 if (temp2 == NULL) return NULL;
2708 len = temp2 - temp1;
2709 if (len <= 0) return NULL;
2710 temp3 = (char*)SMB_MALLOC(len);
2711 if (temp3 == NULL) {
2712 DEBUG(1,("Malloc failure in sstring_sub\n"));
2715 memcpy(temp3, temp1+1, len-1);
2716 temp3[len-1] = '\0';
2720 /********************************************************************
2721 Check a string for any occurrences of a specified list of invalid
2723 ********************************************************************/
2725 bool validate_net_name( const char *name,
2726 const char *invalid_chars,
2731 for ( i=0; i<max_len && name[i]; i++ ) {
2732 /* fail if strchr_m() finds one of the invalid characters */
2733 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
2743 return the number of bytes occupied by a buffer in ASCII format
2744 the result includes the null termination
2745 limited by 'n' bytes
2747 size_t ascii_len_n(const char *src, size_t n)
2751 len = strnlen(src, n);
2760 return the number of bytes occupied by a buffer in CH_UTF16 format
2761 the result includes the null termination
2763 size_t utf16_len(const void *buf)
2767 for (len = 0; SVAL(buf,len); len += 2) ;
2773 return the number of bytes occupied by a buffer in CH_UTF16 format
2774 the result includes the null termination
2775 limited by 'n' bytes
2777 size_t utf16_len_n(const void *src, size_t n)
2781 for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
2790 /*******************************************************************
2791 Add a shell escape character '\' to any character not in a known list
2792 of characters. UNIX charset format.
2793 *******************************************************************/
2795 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
2796 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
2798 char *escape_shell_string(const char *src)
2800 size_t srclen = strlen(src);
2801 char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
2803 bool in_s_quote = false;
2804 bool in_d_quote = false;
2805 bool next_escaped = false;
2813 codepoint_t c = next_codepoint(src, &c_size);
2815 if (c == INVALID_CODEPOINT) {
2821 memcpy(dest, src, c_size);
2824 next_escaped = false;
2829 * Deal with backslash escaped state.
2830 * This only lasts for one character.
2835 next_escaped = false;
2840 * Deal with single quote state. The
2841 * only thing we care about is exiting
2854 * Deal with double quote state. The most
2855 * complex state. We must cope with \, meaning
2856 * possibly escape next char (depending what it
2857 * is), ", meaning exit this state, and possibly
2858 * add an \ escape to any unprotected character
2859 * (listed in INSIDE_DQUOTE_LIST).
2865 * Next character might be escaped.
2866 * We have to peek. Inside double
2867 * quotes only INSIDE_DQUOTE_LIST
2868 * characters are escaped by a \.
2873 c = next_codepoint(&src[1], &c_size);
2874 if (c == INVALID_CODEPOINT) {
2880 * Don't escape the next char.
2889 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
2891 next_escaped = true;
2898 /* Exit double quote state. */
2905 * We know the character isn't \ or ",
2906 * so escape it if it's any of the other
2907 * possible unprotected characters.
2910 if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
2918 * From here to the end of the loop we're
2919 * not in the single or double quote state.
2923 /* Next character must be escaped. */
2924 next_escaped = true;
2930 /* Go into single quote state. */
2937 /* Go into double quote state. */
2943 /* Check if we need to escape the character. */
2945 if (!strchr(INCLUDE_LIST, (int)*src)) {