Remove some globals
[Samba/gbeck.git] / source3 / lib / util_str.c
blobf26c8b8a77f73a8f15c24a97d610ce6cf0e30c59
1 /*
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/>.
25 #include "includes.h"
27 /**
28 * @file
29 * @brief String utilities.
30 **/
32 /**
33 * Internal function to get the next token from a string, return false if none
34 * found. Handles double-quotes. This is the work horse function called by
35 * next_token() and next_token_no_ltrim().
37 * Based on a routine by GJC@VILLAGE.COM.
38 * Extensively modified by Andrew.Tridgell@anu.edu.au
40 static bool next_token_internal(const char **ptr,
41 char *buff,
42 const char *sep,
43 size_t bufsize,
44 bool ltrim)
46 char *s;
47 char *pbuf;
48 bool quoted;
49 size_t len=1;
51 if (!ptr)
52 return(false);
54 s = (char *)*ptr;
56 /* default to simple separators */
57 if (!sep)
58 sep = " \t\n\r";
60 /* find the first non sep char, if left-trimming is requested */
61 if (ltrim) {
62 while (*s && strchr_m(sep,*s))
63 s++;
66 /* nothing left? */
67 if (! *s)
68 return(false);
70 /* copy over the token */
71 pbuf = buff;
72 for (quoted = false; len < bufsize && *s &&
73 (quoted || !strchr_m(sep,*s)); s++) {
74 if ( *s == '\"' ) {
75 quoted = !quoted;
76 } else {
77 len++;
78 *pbuf++ = *s;
82 *ptr = (*s) ? s+1 : s;
83 *pbuf = 0;
85 return(true);
88 static bool next_token_internal_talloc(TALLOC_CTX *ctx,
89 const char **ptr,
90 char **pp_buff,
91 const char *sep,
92 bool ltrim)
94 char *s;
95 char *saved_s;
96 char *pbuf;
97 bool quoted;
98 size_t len=1;
100 *pp_buff = NULL;
101 if (!ptr) {
102 return(false);
105 s = (char *)*ptr;
107 /* default to simple separators */
108 if (!sep) {
109 sep = " \t\n\r";
112 /* find the first non sep char, if left-trimming is requested */
113 if (ltrim) {
114 while (*s && strchr_m(sep,*s))
115 s++;
118 /* nothing left? */
119 if (!*s) {
120 return false;
123 /* When restarting we need to go from here. */
124 saved_s = s;
126 /* Work out the length needed. */
127 for (quoted = false; *s &&
128 (quoted || !strchr_m(sep,*s)); s++) {
129 if (*s == '\"') {
130 quoted = !quoted;
131 } else {
132 len++;
136 /* We started with len = 1 so we have space for the nul. */
137 *pp_buff = TALLOC_ARRAY(ctx, char, len);
138 if (!*pp_buff) {
139 return false;
142 /* copy over the token */
143 pbuf = *pp_buff;
144 s = saved_s;
145 for (quoted = false; *s &&
146 (quoted || !strchr_m(sep,*s)); s++) {
147 if ( *s == '\"' ) {
148 quoted = !quoted;
149 } else {
150 *pbuf++ = *s;
154 *ptr = (*s) ? s+1 : s;
155 *pbuf = 0;
157 return true;
161 * Get the next token from a string, return false if none found. Handles
162 * double-quotes. This version trims leading separator characters before
163 * looking for a token.
165 bool next_token(const char **ptr, char *buff, const char *sep, size_t bufsize)
167 return next_token_internal(ptr, buff, sep, bufsize, true);
170 bool next_token_talloc(TALLOC_CTX *ctx,
171 const char **ptr,
172 char **pp_buff,
173 const char *sep)
175 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, true);
179 * Get the next token from a string, return false if none found. Handles
180 * double-quotes. This version does not trim leading separator characters
181 * before looking for a token.
183 bool next_token_no_ltrim(const char **ptr,
184 char *buff,
185 const char *sep,
186 size_t bufsize)
188 return next_token_internal(ptr, buff, sep, bufsize, false);
191 bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx,
192 const char **ptr,
193 char **pp_buff,
194 const char *sep)
196 return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false);
200 This is like next_token but is not re-entrant and "remembers" the first
201 parameter so you can pass NULL. This is useful for user interface code
202 but beware the fact that it is not re-entrant!
205 static const char *last_ptr=NULL;
207 bool next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
209 bool ret;
210 if (!ptr) {
211 ptr = &last_ptr;
214 ret = next_token(ptr, buff, sep, bufsize);
215 last_ptr = *ptr;
216 return ret;
219 bool next_token_nr_talloc(TALLOC_CTX *ctx,
220 const char **ptr,
221 char **pp_buff,
222 const char *sep)
224 bool ret;
225 if (!ptr) {
226 ptr = &last_ptr;
229 ret = next_token_talloc(ctx, ptr, pp_buff, sep);
230 last_ptr = *ptr;
231 return ret;
234 void set_first_token(char *ptr)
236 last_ptr = ptr;
240 Convert list of tokens to array; dependent on above routine.
241 Uses last_ptr from above - bit of a hack.
244 char **toktocliplist(int *ctok, const char *sep)
246 char *s=(char *)last_ptr;
247 int ictok=0;
248 char **ret, **iret;
250 if (!sep)
251 sep = " \t\n\r";
253 while(*s && strchr_m(sep,*s))
254 s++;
256 /* nothing left? */
257 if (!*s)
258 return(NULL);
260 do {
261 ictok++;
262 while(*s && (!strchr_m(sep,*s)))
263 s++;
264 while(*s && strchr_m(sep,*s))
265 *s++=0;
266 } while(*s);
268 *ctok=ictok;
269 s=(char *)last_ptr;
271 if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1)))
272 return NULL;
274 while(ictok--) {
275 *iret++=s;
276 if (ictok > 0) {
277 while(*s++)
279 while(!*s)
280 s++;
284 ret[*ctok] = NULL;
285 return ret;
289 * Case insensitive string compararison.
291 * iconv does not directly give us a way to compare strings in
292 * arbitrary unix character sets -- all we can is convert and then
293 * compare. This is expensive.
295 * As an optimization, we do a first pass that considers only the
296 * prefix of the strings that is entirely 7-bit. Within this, we
297 * check whether they have the same value.
299 * Hopefully this will often give the answer without needing to copy.
300 * In particular it should speed comparisons to literal ascii strings
301 * or comparisons of strings that are "obviously" different.
303 * If we find a non-ascii character we fall back to converting via
304 * iconv.
306 * This should never be slower than convering the whole thing, and
307 * often faster.
309 * A different optimization would be to compare for bitwise equality
310 * in the binary encoding. (It would be possible thought hairy to do
311 * both simultaneously.) But in that case if they turn out to be
312 * different, we'd need to restart the whole thing.
314 * Even better is to implement strcasecmp for each encoding and use a
315 * function pointer.
317 int StrCaseCmp(const char *s, const char *t)
320 const char *ps, *pt;
321 size_t size;
322 smb_ucs2_t *buffer_s, *buffer_t;
323 int ret;
325 for (ps = s, pt = t; ; ps++, pt++) {
326 char us, ut;
328 if (!*ps && !*pt)
329 return 0; /* both ended */
330 else if (!*ps)
331 return -1; /* s is a prefix */
332 else if (!*pt)
333 return +1; /* t is a prefix */
334 else if ((*ps & 0x80) || (*pt & 0x80))
335 /* not ascii anymore, do it the hard way
336 * from here on in */
337 break;
339 us = toupper_ascii(*ps);
340 ut = toupper_ascii(*pt);
341 if (us == ut)
342 continue;
343 else if (us < ut)
344 return -1;
345 else if (us > ut)
346 return +1;
349 size = push_ucs2_allocate(&buffer_s, ps);
350 if (size == (size_t)-1) {
351 return strcmp(ps, pt);
352 /* Not quite the right answer, but finding the right one
353 under this failure case is expensive, and it's pretty
354 close */
357 size = push_ucs2_allocate(&buffer_t, pt);
358 if (size == (size_t)-1) {
359 SAFE_FREE(buffer_s);
360 return strcmp(ps, pt);
361 /* Not quite the right answer, but finding the right one
362 under this failure case is expensive, and it's pretty
363 close */
366 ret = strcasecmp_w(buffer_s, buffer_t);
367 SAFE_FREE(buffer_s);
368 SAFE_FREE(buffer_t);
369 return ret;
374 Case insensitive string compararison, length limited.
376 int StrnCaseCmp(const char *s, const char *t, size_t len)
378 size_t n = 0;
379 const char *ps, *pt;
380 size_t size;
381 smb_ucs2_t *buffer_s, *buffer_t;
382 int ret;
384 for (ps = s, pt = t; n < len ; ps++, pt++, n++) {
385 char us, ut;
387 if (!*ps && !*pt)
388 return 0; /* both ended */
389 else if (!*ps)
390 return -1; /* s is a prefix */
391 else if (!*pt)
392 return +1; /* t is a prefix */
393 else if ((*ps & 0x80) || (*pt & 0x80))
394 /* not ascii anymore, do it the
395 * hard way from here on in */
396 break;
398 us = toupper_ascii(*ps);
399 ut = toupper_ascii(*pt);
400 if (us == ut)
401 continue;
402 else if (us < ut)
403 return -1;
404 else if (us > ut)
405 return +1;
408 if (n == len) {
409 return 0;
412 size = push_ucs2_allocate(&buffer_s, ps);
413 if (size == (size_t)-1) {
414 return strncmp(ps, pt, len-n);
415 /* Not quite the right answer, but finding the right one
416 under this failure case is expensive,
417 and it's pretty close */
420 size = push_ucs2_allocate(&buffer_t, pt);
421 if (size == (size_t)-1) {
422 SAFE_FREE(buffer_s);
423 return strncmp(ps, pt, len-n);
424 /* Not quite the right answer, but finding the right one
425 under this failure case is expensive,
426 and it's pretty close */
429 ret = strncasecmp_w(buffer_s, buffer_t, len-n);
430 SAFE_FREE(buffer_s);
431 SAFE_FREE(buffer_t);
432 return ret;
436 * Compare 2 strings.
438 * @note The comparison is case-insensitive.
440 bool strequal(const char *s1, const char *s2)
442 if (s1 == s2)
443 return(true);
444 if (!s1 || !s2)
445 return(false);
447 return(StrCaseCmp(s1,s2)==0);
451 * Compare 2 strings up to and including the nth char.
453 * @note The comparison is case-insensitive.
455 bool strnequal(const char *s1,const char *s2,size_t n)
457 if (s1 == s2)
458 return(true);
459 if (!s1 || !s2 || !n)
460 return(false);
462 return(StrnCaseCmp(s1,s2,n)==0);
466 Compare 2 strings (case sensitive).
469 bool strcsequal(const char *s1,const char *s2)
471 if (s1 == s2)
472 return(true);
473 if (!s1 || !s2)
474 return(false);
476 return(strcmp(s1,s2)==0);
480 Do a case-insensitive, whitespace-ignoring string compare.
483 int strwicmp(const char *psz1, const char *psz2)
485 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
486 /* appropriate value. */
487 if (psz1 == psz2)
488 return (0);
489 else if (psz1 == NULL)
490 return (-1);
491 else if (psz2 == NULL)
492 return (1);
494 /* sync the strings on first non-whitespace */
495 while (1) {
496 while (isspace((int)*psz1))
497 psz1++;
498 while (isspace((int)*psz2))
499 psz2++;
500 if (toupper_ascii(*psz1) != toupper_ascii(*psz2) ||
501 *psz1 == '\0' || *psz2 == '\0')
502 break;
503 psz1++;
504 psz2++;
506 return (*psz1 - *psz2);
510 Convert a string to "normal" form.
513 void strnorm(char *s, int case_default)
515 if (case_default == CASE_UPPER)
516 strupper_m(s);
517 else
518 strlower_m(s);
522 Check if a string is in "normal" case.
525 bool strisnormal(const char *s, int case_default)
527 if (case_default == CASE_UPPER)
528 return(!strhaslower(s));
530 return(!strhasupper(s));
535 String replace.
536 NOTE: oldc and newc must be 7 bit characters
538 void string_replace( char *s, char oldc, char newc )
540 char *p;
542 /* this is quite a common operation, so we want it to be
543 fast. We optimise for the ascii case, knowing that all our
544 supported multi-byte character sets are ascii-compatible
545 (ie. they match for the first 128 chars) */
547 for (p = s; *p; p++) {
548 if (*p & 0x80) /* mb string - slow path. */
549 break;
550 if (*p == oldc) {
551 *p = newc;
555 if (!*p)
556 return;
558 /* Slow (mb) path. */
559 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
560 /* With compose characters we must restart from the beginning. JRA. */
561 p = s;
562 #endif
564 while (*p) {
565 size_t c_size;
566 next_codepoint(p, &c_size);
568 if (c_size == 1) {
569 if (*p == oldc) {
570 *p = newc;
573 p += c_size;
578 * Skip past some strings in a buffer - old version - no checks.
579 * **/
581 char *push_skip_string(char *buf)
583 buf += strlen(buf) + 1;
584 return(buf);
588 Skip past a string in a buffer. Buffer may not be
589 null terminated. end_ptr points to the first byte after
590 then end of the buffer.
593 char *skip_string(const char *base, size_t len, char *buf)
595 const char *end_ptr = base + len;
597 if (end_ptr < base || !base || !buf || buf >= end_ptr) {
598 return NULL;
601 /* Skip the string */
602 while (*buf) {
603 buf++;
604 if (buf >= end_ptr) {
605 return NULL;
608 /* Skip the '\0' */
609 buf++;
610 return buf;
614 Count the number of characters in a string. Normally this will
615 be the same as the number of bytes in a string for single byte strings,
616 but will be different for multibyte.
619 size_t str_charnum(const char *s)
621 size_t ret;
622 smb_ucs2_t *tmpbuf2 = NULL;
623 if (push_ucs2_allocate(&tmpbuf2, s) == (size_t)-1) {
624 return 0;
626 ret = strlen_w(tmpbuf2);
627 SAFE_FREE(tmpbuf2);
628 return ret;
632 Count the number of characters in a string. Normally this will
633 be the same as the number of bytes in a string for single byte strings,
634 but will be different for multibyte.
637 size_t str_ascii_charnum(const char *s)
639 size_t ret;
640 char *tmpbuf2 = NULL;
641 if (push_ascii_allocate(&tmpbuf2, s) == (size_t)-1) {
642 return 0;
644 ret = strlen(tmpbuf2);
645 SAFE_FREE(tmpbuf2);
646 return ret;
649 bool trim_char(char *s,char cfront,char cback)
651 bool ret = false;
652 char *ep;
653 char *fp = s;
655 /* Ignore null or empty strings. */
656 if (!s || (s[0] == '\0'))
657 return false;
659 if (cfront) {
660 while (*fp && *fp == cfront)
661 fp++;
662 if (!*fp) {
663 /* We ate the string. */
664 s[0] = '\0';
665 return true;
667 if (fp != s)
668 ret = true;
671 ep = fp + strlen(fp) - 1;
672 if (cback) {
673 /* Attempt ascii only. Bail for mb strings. */
674 while ((ep >= fp) && (*ep == cback)) {
675 ret = true;
676 if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
677 /* Could be mb... bail back to tim_string. */
678 char fs[2], bs[2];
679 if (cfront) {
680 fs[0] = cfront;
681 fs[1] = '\0';
683 bs[0] = cback;
684 bs[1] = '\0';
685 return trim_string(s, cfront ? fs : NULL, bs);
686 } else {
687 ep--;
690 if (ep < fp) {
691 /* We ate the string. */
692 s[0] = '\0';
693 return true;
697 ep[1] = '\0';
698 memmove(s, fp, ep-fp+2);
699 return ret;
703 Trim the specified elements off the front and back of a string.
706 bool trim_string(char *s,const char *front,const char *back)
708 bool ret = false;
709 size_t front_len;
710 size_t back_len;
711 size_t len;
713 /* Ignore null or empty strings. */
714 if (!s || (s[0] == '\0'))
715 return false;
717 front_len = front? strlen(front) : 0;
718 back_len = back? strlen(back) : 0;
720 len = strlen(s);
722 if (front_len) {
723 while (len && strncmp(s, front, front_len)==0) {
724 /* Must use memmove here as src & dest can
725 * easily overlap. Found by valgrind. JRA. */
726 memmove(s, s+front_len, (len-front_len)+1);
727 len -= front_len;
728 ret=true;
732 if (back_len) {
733 while ((len >= back_len) &&
734 strncmp(s+len-back_len,back,back_len)==0) {
735 s[len-back_len]='\0';
736 len -= back_len;
737 ret=true;
740 return ret;
744 Does a string have any uppercase chars in it?
747 bool strhasupper(const char *s)
749 smb_ucs2_t *tmp, *p;
750 bool ret;
752 if (push_ucs2_allocate(&tmp, s) == -1) {
753 return false;
756 for(p = tmp; *p != 0; p++) {
757 if(isupper_w(*p)) {
758 break;
762 ret = (*p != 0);
763 SAFE_FREE(tmp);
764 return ret;
768 Does a string have any lowercase chars in it?
771 bool strhaslower(const char *s)
773 smb_ucs2_t *tmp, *p;
774 bool ret;
776 if (push_ucs2_allocate(&tmp, s) == -1) {
777 return false;
780 for(p = tmp; *p != 0; p++) {
781 if(islower_w(*p)) {
782 break;
786 ret = (*p != 0);
787 SAFE_FREE(tmp);
788 return ret;
792 Find the number of 'c' chars in a string
795 size_t count_chars(const char *s,char c)
797 smb_ucs2_t *ptr;
798 int count;
799 smb_ucs2_t *alloc_tmpbuf = NULL;
801 if (push_ucs2_allocate(&alloc_tmpbuf, s) == (size_t)-1) {
802 return 0;
805 for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++)
806 if(*ptr==UCS2_CHAR(c))
807 count++;
809 SAFE_FREE(alloc_tmpbuf);
810 return(count);
814 Safe string copy into a known length string. maxlength does not
815 include the terminating zero.
818 char *safe_strcpy_fn(const char *fn,
819 int line,
820 char *dest,
821 const char *src,
822 size_t maxlength)
824 size_t len;
826 if (!dest) {
827 DEBUG(0,("ERROR: NULL dest in safe_strcpy, "
828 "called from [%s][%d]\n", fn, line));
829 return NULL;
832 #ifdef DEVELOPER
833 clobber_region(fn,line,dest, maxlength+1);
834 #endif
836 if (!src) {
837 *dest = 0;
838 return dest;
841 len = strnlen(src, maxlength+1);
843 if (len > maxlength) {
844 DEBUG(0,("ERROR: string overflow by "
845 "%lu (%lu - %lu) in safe_strcpy [%.50s]\n",
846 (unsigned long)(len-maxlength), (unsigned long)len,
847 (unsigned long)maxlength, src));
848 len = maxlength;
851 memmove(dest, src, len);
852 dest[len] = 0;
853 return dest;
857 Safe string cat into a string. maxlength does not
858 include the terminating zero.
860 char *safe_strcat_fn(const char *fn,
861 int line,
862 char *dest,
863 const char *src,
864 size_t maxlength)
866 size_t src_len, dest_len;
868 if (!dest) {
869 DEBUG(0,("ERROR: NULL dest in safe_strcat, "
870 "called from [%s][%d]\n", fn, line));
871 return NULL;
874 if (!src)
875 return dest;
877 src_len = strnlen(src, maxlength + 1);
878 dest_len = strnlen(dest, maxlength + 1);
880 #ifdef DEVELOPER
881 clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
882 #endif
884 if (src_len + dest_len > maxlength) {
885 DEBUG(0,("ERROR: string overflow by %d "
886 "in safe_strcat [%.50s]\n",
887 (int)(src_len + dest_len - maxlength), src));
888 if (maxlength > dest_len) {
889 memcpy(&dest[dest_len], src, maxlength - dest_len);
891 dest[maxlength] = 0;
892 return NULL;
895 memcpy(&dest[dest_len], src, src_len);
896 dest[dest_len + src_len] = 0;
897 return dest;
901 Paranoid strcpy into a buffer of given length (includes terminating
902 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
903 and replaces with '_'. Deliberately does *NOT* check for multibyte
904 characters. Don't change it !
907 char *alpha_strcpy_fn(const char *fn,
908 int line,
909 char *dest,
910 const char *src,
911 const char *other_safe_chars,
912 size_t maxlength)
914 size_t len, i;
916 #ifdef DEVELOPER
917 clobber_region(fn, line, dest, maxlength);
918 #endif
920 if (!dest) {
921 DEBUG(0,("ERROR: NULL dest in alpha_strcpy, "
922 "called from [%s][%d]\n", fn, line));
923 return NULL;
926 if (!src) {
927 *dest = 0;
928 return dest;
931 len = strlen(src);
932 if (len >= maxlength)
933 len = maxlength - 1;
935 if (!other_safe_chars)
936 other_safe_chars = "";
938 for(i = 0; i < len; i++) {
939 int val = (src[i] & 0xff);
940 if (isupper_ascii(val) || islower_ascii(val) ||
941 isdigit(val) || strchr_m(other_safe_chars, val))
942 dest[i] = src[i];
943 else
944 dest[i] = '_';
947 dest[i] = '\0';
949 return dest;
953 Like strncpy but always null terminates. Make sure there is room!
954 The variable n should always be one less than the available size.
956 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
958 char *d = dest;
960 #ifdef DEVELOPER
961 clobber_region(fn, line, dest, n+1);
962 #endif
964 if (!dest) {
965 DEBUG(0,("ERROR: NULL dest in StrnCpy, "
966 "called from [%s][%d]\n", fn, line));
967 return(NULL);
970 if (!src) {
971 *dest = 0;
972 return(dest);
975 while (n-- && (*d = *src)) {
976 d++;
977 src++;
980 *d = 0;
981 return(dest);
984 #if 0
986 Like strncpy but copies up to the character marker. always null terminates.
987 returns a pointer to the character marker in the source string (src).
990 static char *strncpyn(char *dest, const char *src, size_t n, char c)
992 char *p;
993 size_t str_len;
995 #ifdef DEVELOPER
996 clobber_region(dest, n+1);
997 #endif
998 p = strchr_m(src, c);
999 if (p == NULL) {
1000 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
1001 return NULL;
1004 str_len = PTR_DIFF(p, src);
1005 strncpy(dest, src, MIN(n, str_len));
1006 dest[str_len] = '\0';
1008 return p;
1010 #endif
1013 Routine to get hex characters and turn them into a 16 byte array.
1014 the array can be variable length, and any non-hex-numeric
1015 characters are skipped. "0xnn" or "0Xnn" is specially catered
1016 for.
1018 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
1022 size_t strhex_to_str(char *buf, size_t buf_len, const char *strhex, size_t strhex_len)
1024 size_t i;
1025 size_t num_chars = 0;
1026 unsigned char lonybble, hinybble;
1027 const char *hexchars = "0123456789ABCDEF";
1028 char *p1 = NULL, *p2 = NULL;
1030 for (i = 0; i < strhex_len && strhex[i] != 0; i++) {
1031 if (strnequal(hexchars, "0x", 2)) {
1032 i++; /* skip two chars */
1033 continue;
1036 if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
1037 break;
1039 i++; /* next hex digit */
1041 if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
1042 break;
1044 /* get the two nybbles */
1045 hinybble = PTR_DIFF(p1, hexchars);
1046 lonybble = PTR_DIFF(p2, hexchars);
1048 if (num_chars >= buf_len) {
1049 break;
1051 buf[num_chars] = (hinybble << 4) | lonybble;
1052 num_chars++;
1054 p1 = NULL;
1055 p2 = NULL;
1057 return num_chars;
1060 DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
1062 DATA_BLOB ret_blob;
1064 if (mem_ctx != NULL)
1065 ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
1066 else
1067 ret_blob = data_blob(NULL, strlen(strhex)/2+1);
1069 ret_blob.length = strhex_to_str((char*)ret_blob.data,
1070 ret_blob.length,
1071 strhex,
1072 strlen(strhex));
1074 return ret_blob;
1078 * Routine to print a buffer as HEX digits, into an allocated string.
1081 char *hex_encode(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
1083 int i;
1084 char *hex_buffer;
1086 hex_buffer = TALLOC_ARRAY(mem_ctx, char, (len*2)+1);
1088 for (i = 0; i < len; i++)
1089 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
1091 return hex_buffer;
1095 Check if a string is part of a list.
1098 bool in_list(const char *s, const char *list, bool casesensitive)
1100 char *tok;
1101 const char *p=list;
1102 size_t bufsize = strlen(list);
1103 bool ret = false;
1105 if (!list)
1106 return(false);
1108 /* We know a token can't be larger
1109 * than the entire list. */
1111 tok = SMB_MALLOC_ARRAY(char, bufsize+1);
1112 if (!tok) {
1113 return false;
1116 while (next_token(&p,tok,LIST_SEP,bufsize+1)) {
1117 if (casesensitive) {
1118 if (strcmp(tok,s) == 0) {
1119 ret = true;
1120 break;
1122 } else {
1123 if (StrCaseCmp(tok,s) == 0) {
1124 ret = true;
1125 break;
1130 SAFE_FREE(tok);
1131 return ret;
1134 /* this is used to prevent lots of mallocs of size 1 */
1135 static const char null_string[] = "";
1138 Set a string value, allocing the space for the string
1141 static bool string_init(char **dest,const char *src)
1143 size_t l;
1145 if (!src)
1146 src = "";
1148 l = strlen(src);
1150 if (l == 0) {
1151 *dest = CONST_DISCARD(char*, null_string);
1152 } else {
1153 (*dest) = SMB_STRDUP(src);
1154 if ((*dest) == NULL) {
1155 DEBUG(0,("Out of memory in string_init\n"));
1156 return false;
1159 return(true);
1163 Free a string value.
1166 void string_free(char **s)
1168 if (!s || !(*s))
1169 return;
1170 if (*s == null_string)
1171 *s = NULL;
1172 SAFE_FREE(*s);
1176 Set a string value, deallocating any existing space, and allocing the space
1177 for the string
1180 bool string_set(char **dest,const char *src)
1182 string_free(dest);
1183 return(string_init(dest,src));
1187 Substitute a string for a pattern in another string. Make sure there is
1188 enough room!
1190 This routine looks for pattern in s and replaces it with
1191 insert. It may do multiple replacements or just one.
1193 Any of " ; ' $ or ` in the insert string are replaced with _
1194 if len==0 then the string cannot be extended. This is different from the old
1195 use of len==0 which was for no length checks to be done.
1198 void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
1199 bool remove_unsafe_characters, bool replace_once,
1200 bool allow_trailing_dollar)
1202 char *p;
1203 ssize_t ls,lp,li, i;
1205 if (!insert || !pattern || !*pattern || !s)
1206 return;
1208 ls = (ssize_t)strlen(s);
1209 lp = (ssize_t)strlen(pattern);
1210 li = (ssize_t)strlen(insert);
1212 if (len == 0)
1213 len = ls + 1; /* len is number of *bytes* */
1215 while (lp <= ls && (p = strstr_m(s,pattern))) {
1216 if (ls + (li-lp) >= len) {
1217 DEBUG(0,("ERROR: string overflow by "
1218 "%d in string_sub(%.50s, %d)\n",
1219 (int)(ls + (li-lp) - len),
1220 pattern, (int)len));
1221 break;
1223 if (li != lp) {
1224 memmove(p+li,p+lp,strlen(p+lp)+1);
1226 for (i=0;i<li;i++) {
1227 switch (insert[i]) {
1228 case '`':
1229 case '"':
1230 case '\'':
1231 case ';':
1232 case '$':
1233 /* allow a trailing $
1234 * (as in machine accounts) */
1235 if (allow_trailing_dollar && (i == li - 1 )) {
1236 p[i] = insert[i];
1237 break;
1239 case '%':
1240 case '\r':
1241 case '\n':
1242 if ( remove_unsafe_characters ) {
1243 p[i] = '_';
1244 /* yes this break should be here
1245 * since we want to fall throw if
1246 * not replacing unsafe chars */
1247 break;
1249 default:
1250 p[i] = insert[i];
1253 s = p + li;
1254 ls += (li-lp);
1256 if (replace_once)
1257 break;
1261 void string_sub_once(char *s, const char *pattern,
1262 const char *insert, size_t len)
1264 string_sub2( s, pattern, insert, len, true, true, false );
1267 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
1269 string_sub2( s, pattern, insert, len, true, false, false );
1272 void fstring_sub(char *s,const char *pattern,const char *insert)
1274 string_sub(s, pattern, insert, sizeof(fstring));
1278 Similar to string_sub2, but it will accept only allocated strings
1279 and may realloc them so pay attention at what you pass on no
1280 pointers inside strings, no pstrings or const may be passed
1281 as string.
1284 char *realloc_string_sub2(char *string,
1285 const char *pattern,
1286 const char *insert,
1287 bool remove_unsafe_characters,
1288 bool allow_trailing_dollar)
1290 char *p, *in;
1291 char *s;
1292 ssize_t ls,lp,li,ld, i;
1294 if (!insert || !pattern || !*pattern || !string || !*string)
1295 return NULL;
1297 s = string;
1299 in = SMB_STRDUP(insert);
1300 if (!in) {
1301 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1302 return NULL;
1304 ls = (ssize_t)strlen(s);
1305 lp = (ssize_t)strlen(pattern);
1306 li = (ssize_t)strlen(insert);
1307 ld = li - lp;
1308 for (i=0;i<li;i++) {
1309 switch (in[i]) {
1310 case '`':
1311 case '"':
1312 case '\'':
1313 case ';':
1314 case '$':
1315 /* allow a trailing $
1316 * (as in machine accounts) */
1317 if (allow_trailing_dollar && (i == li - 1 )) {
1318 break;
1320 case '%':
1321 case '\r':
1322 case '\n':
1323 if ( remove_unsafe_characters ) {
1324 in[i] = '_';
1325 break;
1327 default:
1328 /* ok */
1329 break;
1333 while ((p = strstr_m(s,pattern))) {
1334 if (ld > 0) {
1335 int offset = PTR_DIFF(s,string);
1336 string = (char *)SMB_REALLOC(string, ls + ld + 1);
1337 if (!string) {
1338 DEBUG(0, ("realloc_string_sub: "
1339 "out of memory!\n"));
1340 SAFE_FREE(in);
1341 return NULL;
1343 p = string + offset + (p - s);
1345 if (li != lp) {
1346 memmove(p+li,p+lp,strlen(p+lp)+1);
1348 memcpy(p, in, li);
1349 s = p + li;
1350 ls += ld;
1352 SAFE_FREE(in);
1353 return string;
1356 char *realloc_string_sub(char *string,
1357 const char *pattern,
1358 const char *insert)
1360 return realloc_string_sub2(string, pattern, insert, true, false);
1364 * Internal guts of talloc_string_sub and talloc_all_string_sub.
1365 * talloc version of string_sub2.
1368 char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
1369 const char *pattern,
1370 const char *insert,
1371 bool remove_unsafe_characters,
1372 bool replace_once,
1373 bool allow_trailing_dollar)
1375 char *p, *in;
1376 char *s;
1377 char *string;
1378 ssize_t ls,lp,li,ld, i;
1380 if (!insert || !pattern || !*pattern || !src || !*src) {
1381 return NULL;
1384 string = talloc_strdup(mem_ctx, src);
1385 if (string == NULL) {
1386 DEBUG(0, ("talloc_string_sub2: "
1387 "talloc_strdup failed\n"));
1388 return NULL;
1391 s = string;
1393 in = SMB_STRDUP(insert);
1394 if (!in) {
1395 DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
1396 return NULL;
1398 ls = (ssize_t)strlen(s);
1399 lp = (ssize_t)strlen(pattern);
1400 li = (ssize_t)strlen(insert);
1401 ld = li - lp;
1403 for (i=0;i<li;i++) {
1404 switch (in[i]) {
1405 case '`':
1406 case '"':
1407 case '\'':
1408 case ';':
1409 case '$':
1410 /* allow a trailing $
1411 * (as in machine accounts) */
1412 if (allow_trailing_dollar && (i == li - 1 )) {
1413 break;
1415 case '%':
1416 case '\r':
1417 case '\n':
1418 if (remove_unsafe_characters) {
1419 in[i] = '_';
1420 break;
1422 default:
1423 /* ok */
1424 break;
1428 while ((p = strstr_m(s,pattern))) {
1429 if (ld > 0) {
1430 int offset = PTR_DIFF(s,string);
1431 string = (char *)TALLOC_REALLOC(mem_ctx, string,
1432 ls + ld + 1);
1433 if (!string) {
1434 DEBUG(0, ("talloc_string_sub: out of "
1435 "memory!\n"));
1436 SAFE_FREE(in);
1437 return NULL;
1439 p = string + offset + (p - s);
1441 if (li != lp) {
1442 memmove(p+li,p+lp,strlen(p+lp)+1);
1444 memcpy(p, in, li);
1445 s = p + li;
1446 ls += ld;
1448 if (replace_once) {
1449 break;
1452 SAFE_FREE(in);
1453 return string;
1456 /* Same as string_sub, but returns a talloc'ed string */
1458 char *talloc_string_sub(TALLOC_CTX *mem_ctx,
1459 const char *src,
1460 const char *pattern,
1461 const char *insert)
1463 return talloc_string_sub2(mem_ctx, src, pattern, insert,
1464 true, false, false);
1468 Similar to string_sub() but allows for any character to be substituted.
1469 Use with caution!
1470 if len==0 then the string cannot be extended. This is different from the old
1471 use of len==0 which was for no length checks to be done.
1474 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1476 char *p;
1477 ssize_t ls,lp,li;
1479 if (!insert || !pattern || !s)
1480 return;
1482 ls = (ssize_t)strlen(s);
1483 lp = (ssize_t)strlen(pattern);
1484 li = (ssize_t)strlen(insert);
1486 if (!*pattern)
1487 return;
1489 if (len == 0)
1490 len = ls + 1; /* len is number of *bytes* */
1492 while (lp <= ls && (p = strstr_m(s,pattern))) {
1493 if (ls + (li-lp) >= len) {
1494 DEBUG(0,("ERROR: string overflow by "
1495 "%d in all_string_sub(%.50s, %d)\n",
1496 (int)(ls + (li-lp) - len),
1497 pattern, (int)len));
1498 break;
1500 if (li != lp) {
1501 memmove(p+li,p+lp,strlen(p+lp)+1);
1503 memcpy(p, insert, li);
1504 s = p + li;
1505 ls += (li-lp);
1509 char *talloc_all_string_sub(TALLOC_CTX *ctx,
1510 const char *src,
1511 const char *pattern,
1512 const char *insert)
1514 return talloc_string_sub2(ctx, src, pattern, insert,
1515 false, false, false);
1518 #if 0
1520 Splits out the front and back at a separator.
1523 static void split_at_last_component(char *path, char *front, char sep,
1524 char *back)
1526 char *p = strrchr_m(path, sep);
1528 if (p != NULL)
1529 *p = 0;
1531 if (front != NULL)
1532 pstrcpy(front, path);
1534 if (p != NULL) {
1535 if (back != NULL)
1536 pstrcpy(back, p+1);
1537 *p = '\\';
1538 } else {
1539 if (back != NULL)
1540 back[0] = 0;
1543 #endif
1546 Write an octal as a string.
1549 char *octal_string(int i)
1551 char *result;
1552 if (i == -1) {
1553 result = talloc_strdup(talloc_tos(), "-1");
1555 else {
1556 result = talloc_asprintf(talloc_tos(), "0%o", i);
1558 SMB_ASSERT(result != NULL);
1559 return result;
1564 Truncate a string at a specified length.
1567 char *string_truncate(char *s, unsigned int length)
1569 if (s && strlen(s) > length)
1570 s[length] = 0;
1571 return s;
1575 Strchr and strrchr_m are very hard to do on general multi-byte strings.
1576 We convert via ucs2 for now.
1579 char *strchr_m(const char *src, char c)
1581 smb_ucs2_t *ws = NULL;
1582 char *s2 = NULL;
1583 smb_ucs2_t *p;
1584 const char *s;
1585 char *ret;
1587 /* characters below 0x3F are guaranteed to not appear in
1588 non-initial position in multi-byte charsets */
1589 if ((c & 0xC0) == 0) {
1590 return strchr(src, c);
1593 /* this is quite a common operation, so we want it to be
1594 fast. We optimise for the ascii case, knowing that all our
1595 supported multi-byte character sets are ascii-compatible
1596 (ie. they match for the first 128 chars) */
1598 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1599 if (*s == c)
1600 return (char *)s;
1603 if (!*s)
1604 return NULL;
1606 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1607 /* With compose characters we must restart from the beginning. JRA. */
1608 s = src;
1609 #endif
1611 if (push_ucs2_allocate(&ws, s)==(size_t)-1) {
1612 /* Wrong answer, but what can we do... */
1613 return strchr(src, c);
1615 p = strchr_w(ws, UCS2_CHAR(c));
1616 if (!p) {
1617 SAFE_FREE(ws);
1618 return NULL;
1620 *p = 0;
1621 if (pull_ucs2_allocate(&s2, ws)==(size_t)-1) {
1622 SAFE_FREE(ws);
1623 /* Wrong answer, but what can we do... */
1624 return strchr(src, c);
1626 ret = (char *)(s+strlen(s2));
1627 SAFE_FREE(ws);
1628 SAFE_FREE(s2);
1629 return ret;
1632 char *strrchr_m(const char *s, char c)
1634 /* characters below 0x3F are guaranteed to not appear in
1635 non-initial position in multi-byte charsets */
1636 if ((c & 0xC0) == 0) {
1637 return strrchr(s, c);
1640 /* this is quite a common operation, so we want it to be
1641 fast. We optimise for the ascii case, knowing that all our
1642 supported multi-byte character sets are ascii-compatible
1643 (ie. they match for the first 128 chars). Also, in Samba
1644 we only search for ascii characters in 'c' and that
1645 in all mb character sets with a compound character
1646 containing c, if 'c' is not a match at position
1647 p, then p[-1] > 0x7f. JRA. */
1650 size_t len = strlen(s);
1651 const char *cp = s;
1652 bool got_mb = false;
1654 if (len == 0)
1655 return NULL;
1656 cp += (len - 1);
1657 do {
1658 if (c == *cp) {
1659 /* Could be a match. Part of a multibyte ? */
1660 if ((cp > s) &&
1661 (((unsigned char)cp[-1]) & 0x80)) {
1662 /* Yep - go slow :-( */
1663 got_mb = true;
1664 break;
1666 /* No - we have a match ! */
1667 return (char *)cp;
1669 } while (cp-- != s);
1670 if (!got_mb)
1671 return NULL;
1674 /* String contained a non-ascii char. Slow path. */
1676 smb_ucs2_t *ws = NULL;
1677 char *s2 = NULL;
1678 smb_ucs2_t *p;
1679 char *ret;
1681 if (push_ucs2_allocate(&ws,s)==(size_t)-1) {
1682 /* Wrong answer, but what can we do. */
1683 return strrchr(s, c);
1685 p = strrchr_w(ws, UCS2_CHAR(c));
1686 if (!p) {
1687 SAFE_FREE(ws);
1688 return NULL;
1690 *p = 0;
1691 if (pull_ucs2_allocate(&s2,ws)==(size_t)-1) {
1692 SAFE_FREE(ws);
1693 /* Wrong answer, but what can we do. */
1694 return strrchr(s, c);
1696 ret = (char *)(s+strlen(s2));
1697 SAFE_FREE(ws);
1698 SAFE_FREE(s2);
1699 return ret;
1703 /***********************************************************************
1704 Return the equivalent of doing strrchr 'n' times - always going
1705 backwards.
1706 ***********************************************************************/
1708 char *strnrchr_m(const char *s, char c, unsigned int n)
1710 smb_ucs2_t *ws = NULL;
1711 char *s2 = NULL;
1712 smb_ucs2_t *p;
1713 char *ret;
1715 if (push_ucs2_allocate(&ws,s)==(size_t)-1) {
1716 /* Too hard to try and get right. */
1717 return NULL;
1719 p = strnrchr_w(ws, UCS2_CHAR(c), n);
1720 if (!p) {
1721 SAFE_FREE(ws);
1722 return NULL;
1724 *p = 0;
1725 if (pull_ucs2_allocate(&s2,ws)==(size_t)-1) {
1726 SAFE_FREE(ws);
1727 /* Too hard to try and get right. */
1728 return NULL;
1730 ret = (char *)(s+strlen(s2));
1731 SAFE_FREE(ws);
1732 SAFE_FREE(s2);
1733 return ret;
1736 /***********************************************************************
1737 strstr_m - We convert via ucs2 for now.
1738 ***********************************************************************/
1740 char *strstr_m(const char *src, const char *findstr)
1742 smb_ucs2_t *p;
1743 smb_ucs2_t *src_w, *find_w;
1744 const char *s;
1745 char *s2;
1746 char *retp;
1748 size_t findstr_len = 0;
1750 /* for correctness */
1751 if (!findstr[0]) {
1752 return (char*)src;
1755 /* Samba does single character findstr calls a *lot*. */
1756 if (findstr[1] == '\0')
1757 return strchr_m(src, *findstr);
1759 /* We optimise for the ascii case, knowing that all our
1760 supported multi-byte character sets are ascii-compatible
1761 (ie. they match for the first 128 chars) */
1763 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1764 if (*s == *findstr) {
1765 if (!findstr_len)
1766 findstr_len = strlen(findstr);
1768 if (strncmp(s, findstr, findstr_len) == 0) {
1769 return (char *)s;
1774 if (!*s)
1775 return NULL;
1777 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
1778 /* 'make check' fails unless we do this */
1780 /* With compose characters we must restart from the beginning. JRA. */
1781 s = src;
1782 #endif
1784 if (push_ucs2_allocate(&src_w, src) == (size_t)-1) {
1785 DEBUG(0,("strstr_m: src malloc fail\n"));
1786 return NULL;
1789 if (push_ucs2_allocate(&find_w, findstr) == (size_t)-1) {
1790 SAFE_FREE(src_w);
1791 DEBUG(0,("strstr_m: find malloc fail\n"));
1792 return NULL;
1795 p = strstr_w(src_w, find_w);
1797 if (!p) {
1798 SAFE_FREE(src_w);
1799 SAFE_FREE(find_w);
1800 return NULL;
1803 *p = 0;
1804 if (pull_ucs2_allocate(&s2, src_w) == (size_t)-1) {
1805 SAFE_FREE(src_w);
1806 SAFE_FREE(find_w);
1807 DEBUG(0,("strstr_m: dest malloc fail\n"));
1808 return NULL;
1810 retp = (char *)(s+strlen(s2));
1811 SAFE_FREE(src_w);
1812 SAFE_FREE(find_w);
1813 SAFE_FREE(s2);
1814 return retp;
1818 Convert a string to lower case.
1821 void strlower_m(char *s)
1823 size_t len;
1824 int errno_save;
1826 /* this is quite a common operation, so we want it to be
1827 fast. We optimise for the ascii case, knowing that all our
1828 supported multi-byte character sets are ascii-compatible
1829 (ie. they match for the first 128 chars) */
1831 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1832 *s = tolower_ascii((unsigned char)*s);
1833 s++;
1836 if (!*s)
1837 return;
1839 /* I assume that lowercased string takes the same number of bytes
1840 * as source string even in UTF-8 encoding. (VIV) */
1841 len = strlen(s) + 1;
1842 errno_save = errno;
1843 errno = 0;
1844 unix_strlower(s,len,s,len);
1845 /* Catch mb conversion errors that may not terminate. */
1846 if (errno)
1847 s[len-1] = '\0';
1848 errno = errno_save;
1852 Convert a string to upper case.
1855 void strupper_m(char *s)
1857 size_t len;
1858 int errno_save;
1860 /* this is quite a common operation, so we want it to be
1861 fast. We optimise for the ascii case, knowing that all our
1862 supported multi-byte character sets are ascii-compatible
1863 (ie. they match for the first 128 chars) */
1865 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1866 *s = toupper_ascii((unsigned char)*s);
1867 s++;
1870 if (!*s)
1871 return;
1873 /* I assume that lowercased string takes the same number of bytes
1874 * as source string even in multibyte encoding. (VIV) */
1875 len = strlen(s) + 1;
1876 errno_save = errno;
1877 errno = 0;
1878 unix_strupper(s,len,s,len);
1879 /* Catch mb conversion errors that may not terminate. */
1880 if (errno)
1881 s[len-1] = '\0';
1882 errno = errno_save;
1886 Count the number of UCS2 characters in a string. Normally this will
1887 be the same as the number of bytes in a string for single byte strings,
1888 but will be different for multibyte.
1891 size_t strlen_m(const char *s)
1893 size_t count = 0;
1895 if (!s) {
1896 return 0;
1899 while (*s && !(((uint8_t)*s) & 0x80)) {
1900 s++;
1901 count++;
1904 if (!*s) {
1905 return count;
1908 while (*s) {
1909 size_t c_size;
1910 codepoint_t c = next_codepoint(s, &c_size);
1911 if (c < 0x10000) {
1912 /* Unicode char fits into 16 bits. */
1913 count += 1;
1914 } else {
1915 /* Double-width unicode char - 32 bits. */
1916 count += 2;
1918 s += c_size;
1921 return count;
1925 Count the number of UCS2 characters in a string including the null
1926 terminator.
1929 size_t strlen_m_term(const char *s)
1931 if (!s) {
1932 return 0;
1934 return strlen_m(s) + 1;
1938 * Weird helper routine for the winreg pipe: If nothing is around, return 0,
1939 * if a string is there, include the terminator.
1942 size_t strlen_m_term_null(const char *s)
1944 size_t len;
1945 if (!s) {
1946 return 0;
1948 len = strlen_m(s);
1949 if (len == 0) {
1950 return 0;
1953 return len+1;
1956 Return a RFC2254 binary string representation of a buffer.
1957 Used in LDAP filters.
1958 Caller must free.
1961 char *binary_string_rfc2254(char *buf, int len)
1963 char *s;
1964 int i, j;
1965 const char *hex = "0123456789ABCDEF";
1966 s = (char *)SMB_MALLOC(len * 3 + 1);
1967 if (!s)
1968 return NULL;
1969 for (j=i=0;i<len;i++) {
1970 s[j] = '\\';
1971 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1972 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1973 j += 3;
1975 s[j] = 0;
1976 return s;
1979 char *binary_string(char *buf, int len)
1981 char *s;
1982 int i, j;
1983 const char *hex = "0123456789ABCDEF";
1984 s = (char *)SMB_MALLOC(len * 2 + 1);
1985 if (!s)
1986 return NULL;
1987 for (j=i=0;i<len;i++) {
1988 s[j] = hex[((unsigned char)buf[i]) >> 4];
1989 s[j+1] = hex[((unsigned char)buf[i]) & 0xF];
1990 j += 2;
1992 s[j] = 0;
1993 return s;
1996 Just a typesafety wrapper for snprintf into a pstring.
1999 int pstr_sprintf(pstring s, const char *fmt, ...)
2001 va_list ap;
2002 int ret;
2004 va_start(ap, fmt);
2005 ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
2006 va_end(ap);
2007 return ret;
2012 Just a typesafety wrapper for snprintf into a fstring.
2015 int fstr_sprintf(fstring s, const char *fmt, ...)
2017 va_list ap;
2018 int ret;
2020 va_start(ap, fmt);
2021 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
2022 va_end(ap);
2023 return ret;
2027 List of Strings manipulation functions
2030 #define S_LIST_ABS 16 /* List Allocation Block Size */
2032 static char **str_list_make_internal(TALLOC_CTX *mem_ctx,
2033 const char *string,
2034 const char *sep)
2036 char **list, **rlist;
2037 const char *str;
2038 char *s;
2039 int num, lsize;
2040 char *tok;
2041 TALLOC_CTX *frame = NULL;
2043 if (!string || !*string)
2044 return NULL;
2045 if (mem_ctx) {
2046 s = talloc_strdup(mem_ctx, string);
2047 } else {
2048 s = SMB_STRDUP(string);
2050 if (!s) {
2051 DEBUG(0,("str_list_make: Unable to allocate memory"));
2052 return NULL;
2054 if (!sep) sep = LIST_SEP;
2056 num = lsize = 0;
2057 list = NULL;
2059 str = s;
2060 frame = talloc_stackframe();
2061 while (next_token_talloc(frame, &str, &tok, sep)) {
2062 if (num == lsize) {
2063 lsize += S_LIST_ABS;
2064 if (mem_ctx) {
2065 rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list,
2066 char *, lsize +1);
2067 } else {
2068 /* We need to keep the old list on
2069 * error so we can free the elements
2070 if the realloc fails. */
2071 rlist =SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list,
2072 char *, lsize +1);
2074 if (!rlist) {
2075 DEBUG(0,("str_list_make: "
2076 "Unable to allocate memory"));
2077 str_list_free(&list);
2078 if (mem_ctx) {
2079 TALLOC_FREE(s);
2080 } else {
2081 SAFE_FREE(s);
2083 TALLOC_FREE(frame);
2084 return NULL;
2085 } else {
2086 list = rlist;
2088 memset (&list[num], 0,
2089 ((sizeof(char**)) * (S_LIST_ABS +1)));
2092 if (mem_ctx) {
2093 list[num] = talloc_strdup(mem_ctx, tok);
2094 } else {
2095 list[num] = SMB_STRDUP(tok);
2098 if (!list[num]) {
2099 DEBUG(0,("str_list_make: Unable to allocate memory"));
2100 str_list_free(&list);
2101 if (mem_ctx) {
2102 TALLOC_FREE(s);
2103 } else {
2104 SAFE_FREE(s);
2106 TALLOC_FREE(frame);
2107 return NULL;
2110 num++;
2113 TALLOC_FREE(frame);
2115 if (mem_ctx) {
2116 TALLOC_FREE(s);
2117 } else {
2118 SAFE_FREE(s);
2121 return list;
2124 char **str_list_make_talloc(TALLOC_CTX *mem_ctx,
2125 const char *string,
2126 const char *sep)
2128 return str_list_make_internal(mem_ctx, string, sep);
2131 char **str_list_make(const char *string, const char *sep)
2133 return str_list_make_internal(NULL, string, sep);
2136 bool str_list_copy(char ***dest, const char **src)
2138 char **list, **rlist;
2139 int num, lsize;
2141 *dest = NULL;
2142 if (!src)
2143 return false;
2145 num = lsize = 0;
2146 list = NULL;
2148 while (src[num]) {
2149 if (num == lsize) {
2150 lsize += S_LIST_ABS;
2151 rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list,
2152 char *, lsize +1);
2153 if (!rlist) {
2154 DEBUG(0,("str_list_copy: "
2155 "Unable to re-allocate memory"));
2156 str_list_free(&list);
2157 return false;
2158 } else {
2159 list = rlist;
2161 memset (&list[num], 0,
2162 ((sizeof(char **)) * (S_LIST_ABS +1)));
2165 list[num] = SMB_STRDUP(src[num]);
2166 if (!list[num]) {
2167 DEBUG(0,("str_list_copy: Unable to allocate memory"));
2168 str_list_free(&list);
2169 return false;
2172 num++;
2175 *dest = list;
2176 return true;
2180 * Return true if all the elements of the list match exactly.
2182 bool str_list_compare(char **list1, char **list2)
2184 int num;
2186 if (!list1 || !list2)
2187 return (list1 == list2);
2189 for (num = 0; list1[num]; num++) {
2190 if (!list2[num])
2191 return false;
2192 if (!strcsequal(list1[num], list2[num]))
2193 return false;
2195 if (list2[num])
2196 return false; /* if list2 has more elements than list1 fail */
2198 return true;
2201 static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list)
2203 char **tlist;
2205 if (!list || !*list)
2206 return;
2207 tlist = *list;
2208 for(; *tlist; tlist++) {
2209 if (mem_ctx) {
2210 TALLOC_FREE(*tlist);
2211 } else {
2212 SAFE_FREE(*tlist);
2215 if (mem_ctx) {
2216 TALLOC_FREE(*tlist);
2217 } else {
2218 SAFE_FREE(*list);
2222 void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list)
2224 str_list_free_internal(mem_ctx, list);
2227 void str_list_free(char ***list)
2229 str_list_free_internal(NULL, list);
2232 /******************************************************************************
2233 *****************************************************************************/
2235 int str_list_count( const char **list )
2237 int i = 0;
2239 if ( ! list )
2240 return 0;
2242 /* count the number of list members */
2244 for ( i=0; *list; i++, list++ );
2246 return i;
2249 /******************************************************************************
2250 version of standard_sub_basic() for string lists; uses alloc_sub_basic()
2251 for the work
2252 *****************************************************************************/
2254 bool str_list_sub_basic( char **list, const char *smb_name,
2255 const char *domain_name )
2257 char *s, *tmpstr;
2259 while ( *list ) {
2260 s = *list;
2261 tmpstr = alloc_sub_basic(smb_name, domain_name, s);
2262 if ( !tmpstr ) {
2263 DEBUG(0,("str_list_sub_basic: "
2264 "alloc_sub_basic() return NULL!\n"));
2265 return false;
2268 SAFE_FREE(*list);
2269 *list = tmpstr;
2271 list++;
2274 return true;
2277 /******************************************************************************
2278 substritute a specific pattern in a string list
2279 *****************************************************************************/
2281 bool str_list_substitute(char **list, const char *pattern, const char *insert)
2283 char *p, *s, *t;
2284 ssize_t ls, lp, li, ld, i, d;
2286 if (!list)
2287 return false;
2288 if (!pattern)
2289 return false;
2290 if (!insert)
2291 return false;
2293 lp = (ssize_t)strlen(pattern);
2294 li = (ssize_t)strlen(insert);
2295 ld = li -lp;
2297 while (*list) {
2298 s = *list;
2299 ls = (ssize_t)strlen(s);
2301 while ((p = strstr_m(s, pattern))) {
2302 t = *list;
2303 d = p -t;
2304 if (ld) {
2305 t = (char *) SMB_MALLOC(ls +ld +1);
2306 if (!t) {
2307 DEBUG(0,("str_list_substitute: "
2308 "Unable to allocate memory"));
2309 return false;
2311 memcpy(t, *list, d);
2312 memcpy(t +d +li, p +lp, ls -d -lp +1);
2313 SAFE_FREE(*list);
2314 *list = t;
2315 ls += ld;
2316 s = t +d +li;
2319 for (i = 0; i < li; i++) {
2320 switch (insert[i]) {
2321 case '`':
2322 case '"':
2323 case '\'':
2324 case ';':
2325 case '$':
2326 case '%':
2327 case '\r':
2328 case '\n':
2329 t[d +i] = '_';
2330 break;
2331 default:
2332 t[d +i] = insert[i];
2337 list++;
2340 return true;
2344 #define IPSTR_LIST_SEP ","
2345 #define IPSTR_LIST_CHAR ','
2348 * Add ip string representation to ipstr list. Used also
2349 * as part of @function ipstr_list_make
2351 * @param ipstr_list pointer to string containing ip list;
2352 * MUST BE already allocated and IS reallocated if necessary
2353 * @param ipstr_size pointer to current size of ipstr_list (might be changed
2354 * as a result of reallocation)
2355 * @param ip IP address which is to be added to list
2356 * @return pointer to string appended with new ip and possibly
2357 * reallocated to new length
2360 static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service)
2362 char *new_ipstr = NULL;
2363 char addr_buf[INET6_ADDRSTRLEN];
2365 /* arguments checking */
2366 if (!ipstr_list || !service) {
2367 return NULL;
2370 print_sockaddr(addr_buf,
2371 sizeof(addr_buf),
2372 &service->ss);
2374 /* attempt to convert ip to a string and append colon separator to it */
2375 if (*ipstr_list) {
2376 if (service->ss.ss_family == AF_INET) {
2377 /* IPv4 */
2378 asprintf(&new_ipstr, "%s%s%s:%d",
2379 *ipstr_list,
2380 IPSTR_LIST_SEP,
2381 addr_buf,
2382 service->port);
2383 } else {
2384 /* IPv6 */
2385 asprintf(&new_ipstr, "%s%s[%s]:%d",
2386 *ipstr_list,
2387 IPSTR_LIST_SEP,
2388 addr_buf,
2389 service->port);
2391 SAFE_FREE(*ipstr_list);
2392 } else {
2393 if (service->ss.ss_family == AF_INET) {
2394 /* IPv4 */
2395 asprintf(&new_ipstr, "%s:%d",
2396 addr_buf,
2397 service->port);
2398 } else {
2399 /* IPv6 */
2400 asprintf(&new_ipstr, "[%s]:%d",
2401 addr_buf,
2402 service->port);
2405 *ipstr_list = new_ipstr;
2406 return *ipstr_list;
2410 * Allocate and initialise an ipstr list using ip adresses
2411 * passed as arguments.
2413 * @param ipstr_list pointer to string meant to be allocated and set
2414 * @param ip_list array of ip addresses to place in the list
2415 * @param ip_count number of addresses stored in ip_list
2416 * @return pointer to allocated ip string
2419 char *ipstr_list_make(char **ipstr_list,
2420 const struct ip_service *ip_list,
2421 int ip_count)
2423 int i;
2425 /* arguments checking */
2426 if (!ip_list || !ipstr_list) {
2427 return 0;
2430 *ipstr_list = NULL;
2432 /* process ip addresses given as arguments */
2433 for (i = 0; i < ip_count; i++) {
2434 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
2437 return (*ipstr_list);
2442 * Parse given ip string list into array of ip addresses
2443 * (as ip_service structures)
2444 * e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
2446 * @param ipstr ip string list to be parsed
2447 * @param ip_list pointer to array of ip addresses which is
2448 * allocated by this function and must be freed by caller
2449 * @return number of succesfully parsed addresses
2452 int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list)
2454 fstring token_str;
2455 size_t count;
2456 int i;
2458 if (!ipstr_list || !ip_list)
2459 return 0;
2461 count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
2462 if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
2463 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n",
2464 (unsigned long)count));
2465 return 0;
2468 for ( i=0; next_token(&ipstr_list, token_str,
2469 IPSTR_LIST_SEP, FSTRING_LEN) && i<count; i++ ) {
2470 char *s = token_str;
2471 char *p = strrchr(token_str, ':');
2473 if (p) {
2474 *p = 0;
2475 (*ip_list)[i].port = atoi(p+1);
2478 /* convert single token to ip address */
2479 if (token_str[0] == '[') {
2480 /* IPv6 address. */
2481 s++;
2482 p = strchr(token_str, ']');
2483 if (!p) {
2484 continue;
2486 *p = '\0';
2488 if (!interpret_string_addr(&(*ip_list)[i].ss,
2490 AI_NUMERICHOST)) {
2491 continue;
2495 return count;
2499 * Safely free ip string list
2501 * @param ipstr_list ip string list to be freed
2504 void ipstr_list_free(char* ipstr_list)
2506 SAFE_FREE(ipstr_list);
2510 Unescape a URL encoded string, in place.
2513 void rfc1738_unescape(char *buf)
2515 char *p=buf;
2517 while (p && *p && (p=strchr_m(p,'%'))) {
2518 int c1 = p[1];
2519 int c2 = p[2];
2521 if (c1 >= '0' && c1 <= '9')
2522 c1 = c1 - '0';
2523 else if (c1 >= 'A' && c1 <= 'F')
2524 c1 = 10 + c1 - 'A';
2525 else if (c1 >= 'a' && c1 <= 'f')
2526 c1 = 10 + c1 - 'a';
2527 else {p++; continue;}
2529 if (c2 >= '0' && c2 <= '9')
2530 c2 = c2 - '0';
2531 else if (c2 >= 'A' && c2 <= 'F')
2532 c2 = 10 + c2 - 'A';
2533 else if (c2 >= 'a' && c2 <= 'f')
2534 c2 = 10 + c2 - 'a';
2535 else {p++; continue;}
2537 *p = (c1<<4) | c2;
2539 memmove(p+1, p+3, strlen(p+3)+1);
2540 p++;
2544 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2547 * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
2549 DATA_BLOB base64_decode_data_blob(const char *s)
2551 int bit_offset, byte_offset, idx, i, n;
2552 DATA_BLOB decoded = data_blob(s, strlen(s)+1);
2553 unsigned char *d = decoded.data;
2554 char *p;
2556 n=i=0;
2558 while (*s && (p=strchr_m(b64,*s))) {
2559 idx = (int)(p - b64);
2560 byte_offset = (i*6)/8;
2561 bit_offset = (i*6)%8;
2562 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
2563 if (bit_offset < 3) {
2564 d[byte_offset] |= (idx << (2-bit_offset));
2565 n = byte_offset+1;
2566 } else {
2567 d[byte_offset] |= (idx >> (bit_offset-2));
2568 d[byte_offset+1] = 0;
2569 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
2570 n = byte_offset+2;
2572 s++; i++;
2575 if ((n > 0) && (*s == '=')) {
2576 n -= 1;
2579 /* fix up length */
2580 decoded.length = n;
2581 return decoded;
2585 * Decode a base64 string in-place - wrapper for the above
2587 void base64_decode_inplace(char *s)
2589 DATA_BLOB decoded = base64_decode_data_blob(s);
2591 if ( decoded.length != 0 ) {
2592 memcpy(s, decoded.data, decoded.length);
2594 /* null terminate */
2595 s[decoded.length] = '\0';
2596 } else {
2597 *s = '\0';
2600 data_blob_free(&decoded);
2604 * Encode a base64 string into a malloc()ed string caller to free.
2606 * From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c
2607 * with adjustments
2610 char *base64_encode_data_blob(DATA_BLOB data)
2612 int bits = 0;
2613 int char_count = 0;
2614 size_t out_cnt, len, output_len;
2615 char *result;
2617 if (!data.length || !data.data)
2618 return NULL;
2620 out_cnt = 0;
2621 len = data.length;
2622 output_len = data.length * 2;
2623 result = TALLOC_ARRAY(talloc_tos(), char, output_len); /* get us plenty of space */
2624 SMB_ASSERT(result != NULL);
2626 while (len-- && out_cnt < (data.length * 2) - 5) {
2627 int c = (unsigned char) *(data.data++);
2628 bits += c;
2629 char_count++;
2630 if (char_count == 3) {
2631 result[out_cnt++] = b64[bits >> 18];
2632 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2633 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2634 result[out_cnt++] = b64[bits & 0x3f];
2635 bits = 0;
2636 char_count = 0;
2637 } else {
2638 bits <<= 8;
2641 if (char_count != 0) {
2642 bits <<= 16 - (8 * char_count);
2643 result[out_cnt++] = b64[bits >> 18];
2644 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2645 if (char_count == 1) {
2646 result[out_cnt++] = '=';
2647 result[out_cnt++] = '=';
2648 } else {
2649 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2650 result[out_cnt++] = '=';
2653 result[out_cnt] = '\0'; /* terminate */
2654 return result;
2657 /* read a SMB_BIG_UINT from a string */
2658 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
2661 SMB_BIG_UINT val = -1;
2662 const char *p = nptr;
2664 if (!p) {
2665 if (entptr) {
2666 *entptr = p;
2668 return val;
2671 while (*p && isspace(*p))
2672 p++;
2674 #ifdef LARGE_SMB_OFF_T
2675 sscanf(p,"%llu",&val);
2676 #else /* LARGE_SMB_OFF_T */
2677 sscanf(p,"%lu",&val);
2678 #endif /* LARGE_SMB_OFF_T */
2679 if (entptr) {
2680 while (*p && isdigit(*p))
2681 p++;
2682 *entptr = p;
2685 return val;
2688 /* Convert a size specification to a count of bytes. We accept the following
2689 * suffixes:
2690 * bytes if there is no suffix
2691 * kK kibibytes
2692 * mM mebibytes
2693 * gG gibibytes
2694 * tT tibibytes
2695 * pP whatever the ISO name for petabytes is
2697 * Returns 0 if the string can't be converted.
2699 SMB_OFF_T conv_str_size(const char * str)
2701 SMB_OFF_T lval;
2702 char * end;
2704 if (str == NULL || *str == '\0') {
2705 return 0;
2708 #ifdef HAVE_STRTOULL
2709 if (sizeof(SMB_OFF_T) == 8) {
2710 lval = strtoull(str, &end, 10 /* base */);
2711 } else {
2712 lval = strtoul(str, &end, 10 /* base */);
2714 #else
2715 lval = strtoul(str, &end, 10 /* base */);
2716 #endif
2718 if (end == NULL || end == str) {
2719 return 0;
2722 if (*end) {
2723 SMB_OFF_T lval_orig = lval;
2725 if (strwicmp(end, "K") == 0) {
2726 lval *= (SMB_OFF_T)1024;
2727 } else if (strwicmp(end, "M") == 0) {
2728 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2729 } else if (strwicmp(end, "G") == 0) {
2730 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2731 (SMB_OFF_T)1024);
2732 } else if (strwicmp(end, "T") == 0) {
2733 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2734 (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2735 } else if (strwicmp(end, "P") == 0) {
2736 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2737 (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2738 (SMB_OFF_T)1024);
2739 } else {
2740 return 0;
2743 /* Primitive attempt to detect wrapping on platforms with
2744 * 4-byte SMB_OFF_T. It's better to let the caller handle
2745 * a failure than some random number.
2747 if (lval_orig <= lval) {
2748 return 0;
2752 return lval;
2755 void string_append(char **left, const char *right)
2757 int new_len = strlen(right) + 1;
2759 if (*left == NULL) {
2760 *left = (char *)SMB_MALLOC(new_len);
2761 *left[0] = '\0';
2762 } else {
2763 new_len += strlen(*left);
2764 *left = (char *)SMB_REALLOC(*left, new_len);
2767 if (*left == NULL) {
2768 return;
2771 safe_strcat(*left, right, new_len-1);
2774 bool add_string_to_array(TALLOC_CTX *mem_ctx,
2775 const char *str, const char ***strings,
2776 int *num)
2778 char *dup_str = talloc_strdup(mem_ctx, str);
2780 *strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings,
2781 const char *, (*num)+1);
2783 if ((*strings == NULL) || (dup_str == NULL)) {
2784 *num = 0;
2785 return false;
2788 (*strings)[*num] = dup_str;
2789 *num += 1;
2790 return true;
2793 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
2794 * error checking in between. The indiation that something weird happened is
2795 * string==NULL */
2797 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
2798 size_t *bufsize, const char *fmt, ...)
2800 va_list ap;
2801 char *newstr;
2802 int ret;
2803 bool increased;
2805 /* len<0 is an internal marker that something failed */
2806 if (*len < 0)
2807 goto error;
2809 if (*string == NULL) {
2810 if (*bufsize == 0)
2811 *bufsize = 128;
2813 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
2814 if (*string == NULL)
2815 goto error;
2818 va_start(ap, fmt);
2819 ret = vasprintf(&newstr, fmt, ap);
2820 va_end(ap);
2822 if (ret < 0)
2823 goto error;
2825 increased = false;
2827 while ((*len)+ret >= *bufsize) {
2828 increased = true;
2829 *bufsize *= 2;
2830 if (*bufsize >= (1024*1024*256))
2831 goto error;
2834 if (increased) {
2835 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
2836 *bufsize);
2837 if (*string == NULL) {
2838 goto error;
2842 StrnCpy((*string)+(*len), newstr, ret);
2843 (*len) += ret;
2844 free(newstr);
2845 return;
2847 error:
2848 *len = -1;
2849 *string = NULL;
2853 * asprintf into a string and strupper_m it after that.
2856 int asprintf_strupper_m(char **strp, const char *fmt, ...)
2858 va_list ap;
2859 char *result;
2860 int ret;
2862 va_start(ap, fmt);
2863 ret = vasprintf(&result, fmt, ap);
2864 va_end(ap);
2866 if (ret == -1)
2867 return -1;
2869 strupper_m(result);
2870 *strp = result;
2871 return ret;
2874 char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
2876 va_list ap;
2877 char *ret;
2879 va_start(ap, fmt);
2880 ret = talloc_vasprintf(t, fmt, ap);
2881 va_end(ap);
2883 if (ret == NULL) {
2884 return NULL;
2886 strupper_m(ret);
2887 return ret;
2891 Returns the substring from src between the first occurrence of
2892 the char "front" and the first occurence of the char "back".
2893 Mallocs the return string which must be freed. Not for use
2894 with wide character strings.
2896 char *sstring_sub(const char *src, char front, char back)
2898 char *temp1, *temp2, *temp3;
2899 ptrdiff_t len;
2901 temp1 = strchr(src, front);
2902 if (temp1 == NULL) return NULL;
2903 temp2 = strchr(src, back);
2904 if (temp2 == NULL) return NULL;
2905 len = temp2 - temp1;
2906 if (len <= 0) return NULL;
2907 temp3 = (char*)SMB_MALLOC(len);
2908 if (temp3 == NULL) {
2909 DEBUG(1,("Malloc failure in sstring_sub\n"));
2910 return NULL;
2912 memcpy(temp3, temp1+1, len-1);
2913 temp3[len-1] = '\0';
2914 return temp3;
2917 /********************************************************************
2918 Check a string for any occurrences of a specified list of invalid
2919 characters.
2920 ********************************************************************/
2922 bool validate_net_name( const char *name,
2923 const char *invalid_chars,
2924 int max_len)
2926 int i;
2928 for ( i=0; i<max_len && name[i]; i++ ) {
2929 /* fail if strchr_m() finds one of the invalid characters */
2930 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
2931 return false;
2935 return true;
2940 return the number of bytes occupied by a buffer in ASCII format
2941 the result includes the null termination
2942 limited by 'n' bytes
2944 size_t ascii_len_n(const char *src, size_t n)
2946 size_t len;
2948 len = strnlen(src, n);
2949 if (len+1 <= n) {
2950 len += 1;
2953 return len;
2957 return the number of bytes occupied by a buffer in CH_UTF16 format
2958 the result includes the null termination
2960 size_t utf16_len(const void *buf)
2962 size_t len;
2964 for (len = 0; SVAL(buf,len); len += 2) ;
2966 return len + 2;
2970 return the number of bytes occupied by a buffer in CH_UTF16 format
2971 the result includes the null termination
2972 limited by 'n' bytes
2974 size_t utf16_len_n(const void *src, size_t n)
2976 size_t len;
2978 for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
2980 if (len+2 <= n) {
2981 len += 2;
2984 return len;
2987 /*******************************************************************
2988 Add a shell escape character '\' to any character not in a known list
2989 of characters. UNIX charset format.
2990 *******************************************************************/
2992 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
2993 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
2995 char *escape_shell_string(const char *src)
2997 size_t srclen = strlen(src);
2998 char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
2999 char *dest = ret;
3000 bool in_s_quote = false;
3001 bool in_d_quote = false;
3002 bool next_escaped = false;
3004 if (!ret) {
3005 return NULL;
3008 while (*src) {
3009 size_t c_size;
3010 codepoint_t c = next_codepoint(src, &c_size);
3012 if (c == INVALID_CODEPOINT) {
3013 SAFE_FREE(ret);
3014 return NULL;
3017 if (c_size > 1) {
3018 memcpy(dest, src, c_size);
3019 src += c_size;
3020 dest += c_size;
3021 next_escaped = false;
3022 continue;
3026 * Deal with backslash escaped state.
3027 * This only lasts for one character.
3030 if (next_escaped) {
3031 *dest++ = *src++;
3032 next_escaped = false;
3033 continue;
3037 * Deal with single quote state. The
3038 * only thing we care about is exiting
3039 * this state.
3042 if (in_s_quote) {
3043 if (*src == '\'') {
3044 in_s_quote = false;
3046 *dest++ = *src++;
3047 continue;
3051 * Deal with double quote state. The most
3052 * complex state. We must cope with \, meaning
3053 * possibly escape next char (depending what it
3054 * is), ", meaning exit this state, and possibly
3055 * add an \ escape to any unprotected character
3056 * (listed in INSIDE_DQUOTE_LIST).
3059 if (in_d_quote) {
3060 if (*src == '\\') {
3062 * Next character might be escaped.
3063 * We have to peek. Inside double
3064 * quotes only INSIDE_DQUOTE_LIST
3065 * characters are escaped by a \.
3068 char nextchar;
3070 c = next_codepoint(&src[1], &c_size);
3071 if (c == INVALID_CODEPOINT) {
3072 SAFE_FREE(ret);
3073 return NULL;
3075 if (c_size > 1) {
3077 * Don't escape the next char.
3078 * Just copy the \.
3080 *dest++ = *src++;
3081 continue;
3084 nextchar = src[1];
3086 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
3087 (int)nextchar)) {
3088 next_escaped = true;
3090 *dest++ = *src++;
3091 continue;
3094 if (*src == '\"') {
3095 /* Exit double quote state. */
3096 in_d_quote = false;
3097 *dest++ = *src++;
3098 continue;
3102 * We know the character isn't \ or ",
3103 * so escape it if it's any of the other
3104 * possible unprotected characters.
3107 if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
3108 *dest++ = '\\';
3110 *dest++ = *src++;
3111 continue;
3115 * From here to the end of the loop we're
3116 * not in the single or double quote state.
3119 if (*src == '\\') {
3120 /* Next character must be escaped. */
3121 next_escaped = true;
3122 *dest++ = *src++;
3123 continue;
3126 if (*src == '\'') {
3127 /* Go into single quote state. */
3128 in_s_quote = true;
3129 *dest++ = *src++;
3130 continue;
3133 if (*src == '\"') {
3134 /* Go into double quote state. */
3135 in_d_quote = true;
3136 *dest++ = *src++;
3137 continue;
3140 /* Check if we need to escape the character. */
3142 if (!strchr(INCLUDE_LIST, (int)*src)) {
3143 *dest++ = '\\';
3145 *dest++ = *src++;
3147 *dest++ = '\0';
3148 return ret;