s3 swat: Add XSRF protection to globals page
[Samba.git] / source3 / lib / util_str.c
blob470152814e36bad86c925b88fbec4f9414780599
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 const char toupper_ascii_fast_table[128] = {
28 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
29 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
30 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
31 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
32 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
33 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
34 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
35 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
38 /**
39 * Case insensitive string compararison.
41 * iconv does not directly give us a way to compare strings in
42 * arbitrary unix character sets -- all we can is convert and then
43 * compare. This is expensive.
45 * As an optimization, we do a first pass that considers only the
46 * prefix of the strings that is entirely 7-bit. Within this, we
47 * check whether they have the same value.
49 * Hopefully this will often give the answer without needing to copy.
50 * In particular it should speed comparisons to literal ascii strings
51 * or comparisons of strings that are "obviously" different.
53 * If we find a non-ascii character we fall back to converting via
54 * iconv.
56 * This should never be slower than convering the whole thing, and
57 * often faster.
59 * A different optimization would be to compare for bitwise equality
60 * in the binary encoding. (It would be possible thought hairy to do
61 * both simultaneously.) But in that case if they turn out to be
62 * different, we'd need to restart the whole thing.
64 * Even better is to implement strcasecmp for each encoding and use a
65 * function pointer.
66 **/
67 int StrCaseCmp(const char *s, const char *t)
70 const char *ps, *pt;
71 size_t size;
72 smb_ucs2_t *buffer_s, *buffer_t;
73 int ret;
75 for (ps = s, pt = t; ; ps++, pt++) {
76 char us, ut;
78 if (!*ps && !*pt)
79 return 0; /* both ended */
80 else if (!*ps)
81 return -1; /* s is a prefix */
82 else if (!*pt)
83 return +1; /* t is a prefix */
84 else if ((*ps & 0x80) || (*pt & 0x80))
85 /* not ascii anymore, do it the hard way
86 * from here on in */
87 break;
89 us = toupper_ascii_fast(*ps);
90 ut = toupper_ascii_fast(*pt);
91 if (us == ut)
92 continue;
93 else if (us < ut)
94 return -1;
95 else if (us > ut)
96 return +1;
99 if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
100 return strcmp(ps, pt);
101 /* Not quite the right answer, but finding the right one
102 under this failure case is expensive, and it's pretty
103 close */
106 if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
107 TALLOC_FREE(buffer_s);
108 return strcmp(ps, pt);
109 /* Not quite the right answer, but finding the right one
110 under this failure case is expensive, and it's pretty
111 close */
114 ret = strcasecmp_w(buffer_s, buffer_t);
115 TALLOC_FREE(buffer_s);
116 TALLOC_FREE(buffer_t);
117 return ret;
122 Case insensitive string compararison, length limited.
124 int StrnCaseCmp(const char *s, const char *t, size_t len)
126 size_t n = 0;
127 const char *ps, *pt;
128 size_t size;
129 smb_ucs2_t *buffer_s, *buffer_t;
130 int ret;
132 for (ps = s, pt = t; n < len ; ps++, pt++, n++) {
133 char us, ut;
135 if (!*ps && !*pt)
136 return 0; /* both ended */
137 else if (!*ps)
138 return -1; /* s is a prefix */
139 else if (!*pt)
140 return +1; /* t is a prefix */
141 else if ((*ps & 0x80) || (*pt & 0x80))
142 /* not ascii anymore, do it the
143 * hard way from here on in */
144 break;
146 us = toupper_ascii_fast(*ps);
147 ut = toupper_ascii_fast(*pt);
148 if (us == ut)
149 continue;
150 else if (us < ut)
151 return -1;
152 else if (us > ut)
153 return +1;
156 if (n == len) {
157 return 0;
160 if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
161 return strncmp(ps, pt, len-n);
162 /* Not quite the right answer, but finding the right one
163 under this failure case is expensive,
164 and it's pretty close */
167 if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
168 TALLOC_FREE(buffer_s);
169 return strncmp(ps, pt, len-n);
170 /* Not quite the right answer, but finding the right one
171 under this failure case is expensive,
172 and it's pretty close */
175 ret = strncasecmp_w(buffer_s, buffer_t, len-n);
176 TALLOC_FREE(buffer_s);
177 TALLOC_FREE(buffer_t);
178 return ret;
182 * Compare 2 strings.
184 * @note The comparison is case-insensitive.
186 bool strequal(const char *s1, const char *s2)
188 if (s1 == s2)
189 return(true);
190 if (!s1 || !s2)
191 return(false);
193 return(StrCaseCmp(s1,s2)==0);
197 * Compare 2 strings up to and including the nth char.
199 * @note The comparison is case-insensitive.
201 bool strnequal(const char *s1,const char *s2,size_t n)
203 if (s1 == s2)
204 return(true);
205 if (!s1 || !s2 || !n)
206 return(false);
208 return(StrnCaseCmp(s1,s2,n)==0);
212 Compare 2 strings (case sensitive).
215 bool strcsequal(const char *s1,const char *s2)
217 if (s1 == s2)
218 return(true);
219 if (!s1 || !s2)
220 return(false);
222 return(strcmp(s1,s2)==0);
226 Do a case-insensitive, whitespace-ignoring string compare.
229 int strwicmp(const char *psz1, const char *psz2)
231 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
232 /* appropriate value. */
233 if (psz1 == psz2)
234 return (0);
235 else if (psz1 == NULL)
236 return (-1);
237 else if (psz2 == NULL)
238 return (1);
240 /* sync the strings on first non-whitespace */
241 while (1) {
242 while (isspace((int)*psz1))
243 psz1++;
244 while (isspace((int)*psz2))
245 psz2++;
246 if (toupper_m(*psz1) != toupper_m(*psz2) ||
247 *psz1 == '\0' || *psz2 == '\0')
248 break;
249 psz1++;
250 psz2++;
252 return (*psz1 - *psz2);
256 Convert a string to "normal" form.
259 void strnorm(char *s, int case_default)
261 if (case_default == CASE_UPPER)
262 strupper_m(s);
263 else
264 strlower_m(s);
268 Check if a string is in "normal" case.
271 bool strisnormal(const char *s, int case_default)
273 if (case_default == CASE_UPPER)
274 return(!strhaslower(s));
276 return(!strhasupper(s));
281 String replace.
282 NOTE: oldc and newc must be 7 bit characters
284 void string_replace( char *s, char oldc, char newc )
286 char *p;
288 /* this is quite a common operation, so we want it to be
289 fast. We optimise for the ascii case, knowing that all our
290 supported multi-byte character sets are ascii-compatible
291 (ie. they match for the first 128 chars) */
293 for (p = s; *p; p++) {
294 if (*p & 0x80) /* mb string - slow path. */
295 break;
296 if (*p == oldc) {
297 *p = newc;
301 if (!*p)
302 return;
304 /* Slow (mb) path. */
305 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
306 /* With compose characters we must restart from the beginning. JRA. */
307 p = s;
308 #endif
310 while (*p) {
311 size_t c_size;
312 next_codepoint(p, &c_size);
314 if (c_size == 1) {
315 if (*p == oldc) {
316 *p = newc;
319 p += c_size;
324 * Skip past some strings in a buffer - old version - no checks.
325 * **/
327 char *push_skip_string(char *buf)
329 buf += strlen(buf) + 1;
330 return(buf);
334 Skip past a string in a buffer. Buffer may not be
335 null terminated. end_ptr points to the first byte after
336 then end of the buffer.
339 char *skip_string(const char *base, size_t len, char *buf)
341 const char *end_ptr = base + len;
343 if (end_ptr < base || !base || !buf || buf >= end_ptr) {
344 return NULL;
347 /* Skip the string */
348 while (*buf) {
349 buf++;
350 if (buf >= end_ptr) {
351 return NULL;
354 /* Skip the '\0' */
355 buf++;
356 return buf;
360 Count the number of characters in a string. Normally this will
361 be the same as the number of bytes in a string for single byte strings,
362 but will be different for multibyte.
365 size_t str_charnum(const char *s)
367 size_t ret, converted_size;
368 smb_ucs2_t *tmpbuf2 = NULL;
369 if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
370 return 0;
372 ret = strlen_w(tmpbuf2);
373 TALLOC_FREE(tmpbuf2);
374 return ret;
378 Count the number of characters in a string. Normally this will
379 be the same as the number of bytes in a string for single byte strings,
380 but will be different for multibyte.
383 size_t str_ascii_charnum(const char *s)
385 size_t ret, converted_size;
386 char *tmpbuf2 = NULL;
387 if (!push_ascii_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
388 return 0;
390 ret = strlen(tmpbuf2);
391 TALLOC_FREE(tmpbuf2);
392 return ret;
395 bool trim_char(char *s,char cfront,char cback)
397 bool ret = false;
398 char *ep;
399 char *fp = s;
401 /* Ignore null or empty strings. */
402 if (!s || (s[0] == '\0'))
403 return false;
405 if (cfront) {
406 while (*fp && *fp == cfront)
407 fp++;
408 if (!*fp) {
409 /* We ate the string. */
410 s[0] = '\0';
411 return true;
413 if (fp != s)
414 ret = true;
417 ep = fp + strlen(fp) - 1;
418 if (cback) {
419 /* Attempt ascii only. Bail for mb strings. */
420 while ((ep >= fp) && (*ep == cback)) {
421 ret = true;
422 if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
423 /* Could be mb... bail back to tim_string. */
424 char fs[2], bs[2];
425 if (cfront) {
426 fs[0] = cfront;
427 fs[1] = '\0';
429 bs[0] = cback;
430 bs[1] = '\0';
431 return trim_string(s, cfront ? fs : NULL, bs);
432 } else {
433 ep--;
436 if (ep < fp) {
437 /* We ate the string. */
438 s[0] = '\0';
439 return true;
443 ep[1] = '\0';
444 memmove(s, fp, ep-fp+2);
445 return ret;
449 Does a string have any uppercase chars in it?
452 bool strhasupper(const char *s)
454 smb_ucs2_t *tmp, *p;
455 bool ret;
456 size_t converted_size;
458 if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) {
459 return false;
462 for(p = tmp; *p != 0; p++) {
463 if(isupper_w(*p)) {
464 break;
468 ret = (*p != 0);
469 TALLOC_FREE(tmp);
470 return ret;
474 Does a string have any lowercase chars in it?
477 bool strhaslower(const char *s)
479 smb_ucs2_t *tmp, *p;
480 bool ret;
481 size_t converted_size;
483 if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) {
484 return false;
487 for(p = tmp; *p != 0; p++) {
488 if(islower_w(*p)) {
489 break;
493 ret = (*p != 0);
494 TALLOC_FREE(tmp);
495 return ret;
499 Safe string copy into a known length string. maxlength does not
500 include the terminating zero.
503 char *safe_strcpy_fn(const char *fn,
504 int line,
505 char *dest,
506 const char *src,
507 size_t maxlength)
509 size_t len;
511 if (!dest) {
512 DEBUG(0,("ERROR: NULL dest in safe_strcpy, "
513 "called from [%s][%d]\n", fn, line));
514 return NULL;
517 #ifdef DEVELOPER
518 clobber_region(fn,line,dest, maxlength+1);
519 #endif
521 if (!src) {
522 *dest = 0;
523 return dest;
526 len = strnlen(src, maxlength+1);
528 if (len > maxlength) {
529 DEBUG(0,("ERROR: string overflow by "
530 "%lu (%lu - %lu) in safe_strcpy [%.50s]\n",
531 (unsigned long)(len-maxlength), (unsigned long)len,
532 (unsigned long)maxlength, src));
533 len = maxlength;
536 memmove(dest, src, len);
537 dest[len] = 0;
538 return dest;
542 Safe string cat into a string. maxlength does not
543 include the terminating zero.
545 char *safe_strcat_fn(const char *fn,
546 int line,
547 char *dest,
548 const char *src,
549 size_t maxlength)
551 size_t src_len, dest_len;
553 if (!dest) {
554 DEBUG(0,("ERROR: NULL dest in safe_strcat, "
555 "called from [%s][%d]\n", fn, line));
556 return NULL;
559 if (!src)
560 return dest;
562 src_len = strnlen(src, maxlength + 1);
563 dest_len = strnlen(dest, maxlength + 1);
565 #ifdef DEVELOPER
566 clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
567 #endif
569 if (src_len + dest_len > maxlength) {
570 DEBUG(0,("ERROR: string overflow by %d "
571 "in safe_strcat [%.50s]\n",
572 (int)(src_len + dest_len - maxlength), src));
573 if (maxlength > dest_len) {
574 memcpy(&dest[dest_len], src, maxlength - dest_len);
576 dest[maxlength] = 0;
577 return NULL;
580 memcpy(&dest[dest_len], src, src_len);
581 dest[dest_len + src_len] = 0;
582 return dest;
586 Paranoid strcpy into a buffer of given length (includes terminating
587 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
588 and replaces with '_'. Deliberately does *NOT* check for multibyte
589 characters. Treats src as an array of bytes, not as a multibyte
590 string. Any byte >0x7f is automatically converted to '_'.
591 other_safe_chars must also contain an ascii string (bytes<0x7f).
594 char *alpha_strcpy_fn(const char *fn,
595 int line,
596 char *dest,
597 const char *src,
598 const char *other_safe_chars,
599 size_t maxlength)
601 size_t len, i;
603 #ifdef DEVELOPER
604 clobber_region(fn, line, dest, maxlength);
605 #endif
607 if (!dest) {
608 DEBUG(0,("ERROR: NULL dest in alpha_strcpy, "
609 "called from [%s][%d]\n", fn, line));
610 return NULL;
613 if (!src) {
614 *dest = 0;
615 return dest;
618 len = strlen(src);
619 if (len >= maxlength)
620 len = maxlength - 1;
622 if (!other_safe_chars)
623 other_safe_chars = "";
625 for(i = 0; i < len; i++) {
626 int val = (src[i] & 0xff);
627 if (val > 0x7f) {
628 dest[i] = '_';
629 continue;
631 if (isupper(val) || islower(val) ||
632 isdigit(val) || strchr(other_safe_chars, val))
633 dest[i] = src[i];
634 else
635 dest[i] = '_';
638 dest[i] = '\0';
640 return dest;
644 Like strncpy but always null terminates. Make sure there is room!
645 The variable n should always be one less than the available size.
647 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
649 char *d = dest;
651 #ifdef DEVELOPER
652 clobber_region(fn, line, dest, n+1);
653 #endif
655 if (!dest) {
656 DEBUG(0,("ERROR: NULL dest in StrnCpy, "
657 "called from [%s][%d]\n", fn, line));
658 return(NULL);
661 if (!src) {
662 *dest = 0;
663 return(dest);
666 while (n-- && (*d = *src)) {
667 d++;
668 src++;
671 *d = 0;
672 return(dest);
675 #if 0
677 Like strncpy but copies up to the character marker. always null terminates.
678 returns a pointer to the character marker in the source string (src).
681 static char *strncpyn(char *dest, const char *src, size_t n, char c)
683 char *p;
684 size_t str_len;
686 #ifdef DEVELOPER
687 clobber_region(dest, n+1);
688 #endif
689 p = strchr_m(src, c);
690 if (p == NULL) {
691 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
692 return NULL;
695 str_len = PTR_DIFF(p, src);
696 strncpy(dest, src, MIN(n, str_len));
697 dest[str_len] = '\0';
699 return p;
701 #endif
704 Check if a string is part of a list.
707 bool in_list(const char *s, const char *list, bool casesensitive)
709 char *tok = NULL;
710 bool ret = false;
711 TALLOC_CTX *frame;
713 if (!list) {
714 return false;
717 frame = talloc_stackframe();
718 while (next_token_talloc(frame, &list, &tok,LIST_SEP)) {
719 if (casesensitive) {
720 if (strcmp(tok,s) == 0) {
721 ret = true;
722 break;
724 } else {
725 if (StrCaseCmp(tok,s) == 0) {
726 ret = true;
727 break;
731 TALLOC_FREE(frame);
732 return ret;
735 /* this is used to prevent lots of mallocs of size 1 */
736 static const char null_string[] = "";
739 Set a string value, allocing the space for the string
742 static bool string_init(char **dest,const char *src)
744 size_t l;
746 if (!src)
747 src = "";
749 l = strlen(src);
751 if (l == 0) {
752 *dest = CONST_DISCARD(char*, null_string);
753 } else {
754 (*dest) = SMB_STRDUP(src);
755 if ((*dest) == NULL) {
756 DEBUG(0,("Out of memory in string_init\n"));
757 return false;
760 return(true);
764 Free a string value.
767 void string_free(char **s)
769 if (!s || !(*s))
770 return;
771 if (*s == null_string)
772 *s = NULL;
773 SAFE_FREE(*s);
777 Set a string value, deallocating any existing space, and allocing the space
778 for the string
781 bool string_set(char **dest,const char *src)
783 string_free(dest);
784 return(string_init(dest,src));
788 Substitute a string for a pattern in another string. Make sure there is
789 enough room!
791 This routine looks for pattern in s and replaces it with
792 insert. It may do multiple replacements or just one.
794 Any of " ; ' $ or ` in the insert string are replaced with _
795 if len==0 then the string cannot be extended. This is different from the old
796 use of len==0 which was for no length checks to be done.
799 void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
800 bool remove_unsafe_characters, bool replace_once,
801 bool allow_trailing_dollar)
803 char *p;
804 ssize_t ls,lp,li, i;
806 if (!insert || !pattern || !*pattern || !s)
807 return;
809 ls = (ssize_t)strlen(s);
810 lp = (ssize_t)strlen(pattern);
811 li = (ssize_t)strlen(insert);
813 if (len == 0)
814 len = ls + 1; /* len is number of *bytes* */
816 while (lp <= ls && (p = strstr_m(s,pattern))) {
817 if (ls + (li-lp) >= len) {
818 DEBUG(0,("ERROR: string overflow by "
819 "%d in string_sub(%.50s, %d)\n",
820 (int)(ls + (li-lp) - len),
821 pattern, (int)len));
822 break;
824 if (li != lp) {
825 memmove(p+li,p+lp,strlen(p+lp)+1);
827 for (i=0;i<li;i++) {
828 switch (insert[i]) {
829 case '$':
830 /* allow a trailing $
831 * (as in machine accounts) */
832 if (allow_trailing_dollar && (i == li - 1 )) {
833 p[i] = insert[i];
834 break;
836 case '`':
837 case '"':
838 case '\'':
839 case ';':
840 case '%':
841 case '\r':
842 case '\n':
843 if ( remove_unsafe_characters ) {
844 p[i] = '_';
845 /* yes this break should be here
846 * since we want to fall throw if
847 * not replacing unsafe chars */
848 break;
850 default:
851 p[i] = insert[i];
854 s = p + li;
855 ls += (li-lp);
857 if (replace_once)
858 break;
862 void string_sub_once(char *s, const char *pattern,
863 const char *insert, size_t len)
865 string_sub2( s, pattern, insert, len, true, true, false );
868 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
870 string_sub2( s, pattern, insert, len, true, false, false );
873 void fstring_sub(char *s,const char *pattern,const char *insert)
875 string_sub(s, pattern, insert, sizeof(fstring));
879 Similar to string_sub2, but it will accept only allocated strings
880 and may realloc them so pay attention at what you pass on no
881 pointers inside strings, no const may be passed
882 as string.
885 char *realloc_string_sub2(char *string,
886 const char *pattern,
887 const char *insert,
888 bool remove_unsafe_characters,
889 bool allow_trailing_dollar)
891 char *p, *in;
892 char *s;
893 ssize_t ls,lp,li,ld, i;
895 if (!insert || !pattern || !*pattern || !string || !*string)
896 return NULL;
898 s = string;
900 in = SMB_STRDUP(insert);
901 if (!in) {
902 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
903 return NULL;
905 ls = (ssize_t)strlen(s);
906 lp = (ssize_t)strlen(pattern);
907 li = (ssize_t)strlen(insert);
908 ld = li - lp;
909 for (i=0;i<li;i++) {
910 switch (in[i]) {
911 case '$':
912 /* allow a trailing $
913 * (as in machine accounts) */
914 if (allow_trailing_dollar && (i == li - 1 )) {
915 break;
917 case '`':
918 case '"':
919 case '\'':
920 case ';':
921 case '%':
922 case '\r':
923 case '\n':
924 if ( remove_unsafe_characters ) {
925 in[i] = '_';
926 break;
928 default:
929 /* ok */
930 break;
934 while ((p = strstr_m(s,pattern))) {
935 if (ld > 0) {
936 int offset = PTR_DIFF(s,string);
937 string = (char *)SMB_REALLOC(string, ls + ld + 1);
938 if (!string) {
939 DEBUG(0, ("realloc_string_sub: "
940 "out of memory!\n"));
941 SAFE_FREE(in);
942 return NULL;
944 p = string + offset + (p - s);
946 if (li != lp) {
947 memmove(p+li,p+lp,strlen(p+lp)+1);
949 memcpy(p, in, li);
950 s = p + li;
951 ls += ld;
953 SAFE_FREE(in);
954 return string;
957 char *realloc_string_sub(char *string,
958 const char *pattern,
959 const char *insert)
961 return realloc_string_sub2(string, pattern, insert, true, false);
965 * Internal guts of talloc_string_sub and talloc_all_string_sub.
966 * talloc version of string_sub2.
969 char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
970 const char *pattern,
971 const char *insert,
972 bool remove_unsafe_characters,
973 bool replace_once,
974 bool allow_trailing_dollar)
976 char *p, *in;
977 char *s;
978 char *string;
979 ssize_t ls,lp,li,ld, i;
981 if (!insert || !pattern || !*pattern || !src) {
982 return NULL;
985 string = talloc_strdup(mem_ctx, src);
986 if (string == NULL) {
987 DEBUG(0, ("talloc_string_sub2: "
988 "talloc_strdup failed\n"));
989 return NULL;
992 s = string;
994 in = SMB_STRDUP(insert);
995 if (!in) {
996 DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
997 return NULL;
999 ls = (ssize_t)strlen(s);
1000 lp = (ssize_t)strlen(pattern);
1001 li = (ssize_t)strlen(insert);
1002 ld = li - lp;
1004 for (i=0;i<li;i++) {
1005 switch (in[i]) {
1006 case '$':
1007 /* allow a trailing $
1008 * (as in machine accounts) */
1009 if (allow_trailing_dollar && (i == li - 1 )) {
1010 break;
1012 case '`':
1013 case '"':
1014 case '\'':
1015 case ';':
1016 case '%':
1017 case '\r':
1018 case '\n':
1019 if (remove_unsafe_characters) {
1020 in[i] = '_';
1021 break;
1023 default:
1024 /* ok */
1025 break;
1029 while ((p = strstr_m(s,pattern))) {
1030 if (ld > 0) {
1031 int offset = PTR_DIFF(s,string);
1032 string = (char *)TALLOC_REALLOC(mem_ctx, string,
1033 ls + ld + 1);
1034 if (!string) {
1035 DEBUG(0, ("talloc_string_sub: out of "
1036 "memory!\n"));
1037 SAFE_FREE(in);
1038 return NULL;
1040 p = string + offset + (p - s);
1042 if (li != lp) {
1043 memmove(p+li,p+lp,strlen(p+lp)+1);
1045 memcpy(p, in, li);
1046 s = p + li;
1047 ls += ld;
1049 if (replace_once) {
1050 break;
1053 SAFE_FREE(in);
1054 return string;
1057 /* Same as string_sub, but returns a talloc'ed string */
1059 char *talloc_string_sub(TALLOC_CTX *mem_ctx,
1060 const char *src,
1061 const char *pattern,
1062 const char *insert)
1064 return talloc_string_sub2(mem_ctx, src, pattern, insert,
1065 true, false, false);
1069 Similar to string_sub() but allows for any character to be substituted.
1070 Use with caution!
1071 if len==0 then the string cannot be extended. This is different from the old
1072 use of len==0 which was for no length checks to be done.
1075 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1077 char *p;
1078 ssize_t ls,lp,li;
1080 if (!insert || !pattern || !s)
1081 return;
1083 ls = (ssize_t)strlen(s);
1084 lp = (ssize_t)strlen(pattern);
1085 li = (ssize_t)strlen(insert);
1087 if (!*pattern)
1088 return;
1090 if (len == 0)
1091 len = ls + 1; /* len is number of *bytes* */
1093 while (lp <= ls && (p = strstr_m(s,pattern))) {
1094 if (ls + (li-lp) >= len) {
1095 DEBUG(0,("ERROR: string overflow by "
1096 "%d in all_string_sub(%.50s, %d)\n",
1097 (int)(ls + (li-lp) - len),
1098 pattern, (int)len));
1099 break;
1101 if (li != lp) {
1102 memmove(p+li,p+lp,strlen(p+lp)+1);
1104 memcpy(p, insert, li);
1105 s = p + li;
1106 ls += (li-lp);
1110 char *talloc_all_string_sub(TALLOC_CTX *ctx,
1111 const char *src,
1112 const char *pattern,
1113 const char *insert)
1115 return talloc_string_sub2(ctx, src, pattern, insert,
1116 false, false, false);
1120 Write an octal as a string.
1123 char *octal_string(int i)
1125 char *result;
1126 if (i == -1) {
1127 result = talloc_strdup(talloc_tos(), "-1");
1129 else {
1130 result = talloc_asprintf(talloc_tos(), "0%o", i);
1132 SMB_ASSERT(result != NULL);
1133 return result;
1138 Truncate a string at a specified length.
1141 char *string_truncate(char *s, unsigned int length)
1143 if (s && strlen(s) > length)
1144 s[length] = 0;
1145 return s;
1149 Strchr and strrchr_m are very hard to do on general multi-byte strings.
1150 We convert via ucs2 for now.
1153 char *strchr_m(const char *src, char c)
1155 smb_ucs2_t *ws = NULL;
1156 char *s2 = NULL;
1157 smb_ucs2_t *p;
1158 const char *s;
1159 char *ret;
1160 size_t converted_size;
1162 /* characters below 0x3F are guaranteed to not appear in
1163 non-initial position in multi-byte charsets */
1164 if ((c & 0xC0) == 0) {
1165 return strchr(src, c);
1168 /* this is quite a common operation, so we want it to be
1169 fast. We optimise for the ascii case, knowing that all our
1170 supported multi-byte character sets are ascii-compatible
1171 (ie. they match for the first 128 chars) */
1173 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1174 if (*s == c)
1175 return (char *)s;
1178 if (!*s)
1179 return NULL;
1181 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1182 /* With compose characters we must restart from the beginning. JRA. */
1183 s = src;
1184 #endif
1186 if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
1187 /* Wrong answer, but what can we do... */
1188 return strchr(src, c);
1190 p = strchr_w(ws, UCS2_CHAR(c));
1191 if (!p) {
1192 TALLOC_FREE(ws);
1193 return NULL;
1195 *p = 0;
1196 if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
1197 SAFE_FREE(ws);
1198 /* Wrong answer, but what can we do... */
1199 return strchr(src, c);
1201 ret = (char *)(s+strlen(s2));
1202 TALLOC_FREE(ws);
1203 TALLOC_FREE(s2);
1204 return ret;
1207 char *strrchr_m(const char *s, char c)
1209 /* characters below 0x3F are guaranteed to not appear in
1210 non-initial position in multi-byte charsets */
1211 if ((c & 0xC0) == 0) {
1212 return strrchr(s, c);
1215 /* this is quite a common operation, so we want it to be
1216 fast. We optimise for the ascii case, knowing that all our
1217 supported multi-byte character sets are ascii-compatible
1218 (ie. they match for the first 128 chars). Also, in Samba
1219 we only search for ascii characters in 'c' and that
1220 in all mb character sets with a compound character
1221 containing c, if 'c' is not a match at position
1222 p, then p[-1] > 0x7f. JRA. */
1225 size_t len = strlen(s);
1226 const char *cp = s;
1227 bool got_mb = false;
1229 if (len == 0)
1230 return NULL;
1231 cp += (len - 1);
1232 do {
1233 if (c == *cp) {
1234 /* Could be a match. Part of a multibyte ? */
1235 if ((cp > s) &&
1236 (((unsigned char)cp[-1]) & 0x80)) {
1237 /* Yep - go slow :-( */
1238 got_mb = true;
1239 break;
1241 /* No - we have a match ! */
1242 return (char *)cp;
1244 } while (cp-- != s);
1245 if (!got_mb)
1246 return NULL;
1249 /* String contained a non-ascii char. Slow path. */
1251 smb_ucs2_t *ws = NULL;
1252 char *s2 = NULL;
1253 smb_ucs2_t *p;
1254 char *ret;
1255 size_t converted_size;
1257 if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
1258 /* Wrong answer, but what can we do. */
1259 return strrchr(s, c);
1261 p = strrchr_w(ws, UCS2_CHAR(c));
1262 if (!p) {
1263 TALLOC_FREE(ws);
1264 return NULL;
1266 *p = 0;
1267 if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
1268 TALLOC_FREE(ws);
1269 /* Wrong answer, but what can we do. */
1270 return strrchr(s, c);
1272 ret = (char *)(s+strlen(s2));
1273 TALLOC_FREE(ws);
1274 TALLOC_FREE(s2);
1275 return ret;
1279 /***********************************************************************
1280 Return the equivalent of doing strrchr 'n' times - always going
1281 backwards.
1282 ***********************************************************************/
1284 char *strnrchr_m(const char *s, char c, unsigned int n)
1286 smb_ucs2_t *ws = NULL;
1287 char *s2 = NULL;
1288 smb_ucs2_t *p;
1289 char *ret;
1290 size_t converted_size;
1292 if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
1293 /* Too hard to try and get right. */
1294 return NULL;
1296 p = strnrchr_w(ws, UCS2_CHAR(c), n);
1297 if (!p) {
1298 TALLOC_FREE(ws);
1299 return NULL;
1301 *p = 0;
1302 if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
1303 TALLOC_FREE(ws);
1304 /* Too hard to try and get right. */
1305 return NULL;
1307 ret = (char *)(s+strlen(s2));
1308 TALLOC_FREE(ws);
1309 TALLOC_FREE(s2);
1310 return ret;
1313 /***********************************************************************
1314 strstr_m - We convert via ucs2 for now.
1315 ***********************************************************************/
1317 char *strstr_m(const char *src, const char *findstr)
1319 smb_ucs2_t *p;
1320 smb_ucs2_t *src_w, *find_w;
1321 const char *s;
1322 char *s2;
1323 char *retp;
1325 size_t converted_size, findstr_len = 0;
1327 /* for correctness */
1328 if (!findstr[0]) {
1329 return (char*)src;
1332 /* Samba does single character findstr calls a *lot*. */
1333 if (findstr[1] == '\0')
1334 return strchr_m(src, *findstr);
1336 /* We optimise for the ascii case, knowing that all our
1337 supported multi-byte character sets are ascii-compatible
1338 (ie. they match for the first 128 chars) */
1340 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1341 if (*s == *findstr) {
1342 if (!findstr_len)
1343 findstr_len = strlen(findstr);
1345 if (strncmp(s, findstr, findstr_len) == 0) {
1346 return (char *)s;
1351 if (!*s)
1352 return NULL;
1354 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
1355 /* 'make check' fails unless we do this */
1357 /* With compose characters we must restart from the beginning. JRA. */
1358 s = src;
1359 #endif
1361 if (!push_ucs2_talloc(talloc_tos(), &src_w, src, &converted_size)) {
1362 DEBUG(0,("strstr_m: src malloc fail\n"));
1363 return NULL;
1366 if (!push_ucs2_talloc(talloc_tos(), &find_w, findstr, &converted_size)) {
1367 TALLOC_FREE(src_w);
1368 DEBUG(0,("strstr_m: find malloc fail\n"));
1369 return NULL;
1372 p = strstr_w(src_w, find_w);
1374 if (!p) {
1375 TALLOC_FREE(src_w);
1376 TALLOC_FREE(find_w);
1377 return NULL;
1380 *p = 0;
1381 if (!pull_ucs2_talloc(talloc_tos(), &s2, src_w, &converted_size)) {
1382 TALLOC_FREE(src_w);
1383 TALLOC_FREE(find_w);
1384 DEBUG(0,("strstr_m: dest malloc fail\n"));
1385 return NULL;
1387 retp = (char *)(s+strlen(s2));
1388 TALLOC_FREE(src_w);
1389 TALLOC_FREE(find_w);
1390 TALLOC_FREE(s2);
1391 return retp;
1395 Convert a string to lower case.
1398 void strlower_m(char *s)
1400 size_t len;
1401 int errno_save;
1403 /* this is quite a common operation, so we want it to be
1404 fast. We optimise for the ascii case, knowing that all our
1405 supported multi-byte character sets are ascii-compatible
1406 (ie. they match for the first 128 chars) */
1408 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1409 *s = tolower_m((unsigned char)*s);
1410 s++;
1413 if (!*s)
1414 return;
1416 /* I assume that lowercased string takes the same number of bytes
1417 * as source string even in UTF-8 encoding. (VIV) */
1418 len = strlen(s) + 1;
1419 errno_save = errno;
1420 errno = 0;
1421 unix_strlower(s,len,s,len);
1422 /* Catch mb conversion errors that may not terminate. */
1423 if (errno)
1424 s[len-1] = '\0';
1425 errno = errno_save;
1429 Convert a string to upper case.
1432 void strupper_m(char *s)
1434 size_t len;
1435 int errno_save;
1437 /* this is quite a common operation, so we want it to be
1438 fast. We optimise for the ascii case, knowing that all our
1439 supported multi-byte character sets are ascii-compatible
1440 (ie. they match for the first 128 chars) */
1442 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1443 *s = toupper_ascii_fast((unsigned char)*s);
1444 s++;
1447 if (!*s)
1448 return;
1450 /* I assume that lowercased string takes the same number of bytes
1451 * as source string even in multibyte encoding. (VIV) */
1452 len = strlen(s) + 1;
1453 errno_save = errno;
1454 errno = 0;
1455 unix_strupper(s,len,s,len);
1456 /* Catch mb conversion errors that may not terminate. */
1457 if (errno)
1458 s[len-1] = '\0';
1459 errno = errno_save;
1463 * Calculate the number of units (8 or 16-bit, depending on the
1464 * destination charset), that would be needed to convert the input
1465 * string which is expected to be in in src_charset encoding to the
1466 * destination charset (which should be a unicode charset).
1469 size_t strlen_m_ext(const char *s, const charset_t src_charset,
1470 const charset_t dst_charset)
1472 size_t count = 0;
1474 if (!s) {
1475 return 0;
1478 while (*s && !(((uint8_t)*s) & 0x80)) {
1479 s++;
1480 count++;
1483 if (!*s) {
1484 return count;
1487 while (*s) {
1488 size_t c_size;
1489 codepoint_t c = next_codepoint_ext(s, src_charset, &c_size);
1490 s += c_size;
1492 switch (dst_charset) {
1493 case CH_UTF16LE:
1494 case CH_UTF16BE:
1495 case CH_UTF16MUNGED:
1496 if (c < 0x10000) {
1497 /* Unicode char fits into 16 bits. */
1498 count += 1;
1499 } else {
1500 /* Double-width unicode char - 32 bits. */
1501 count += 2;
1503 break;
1504 case CH_UTF8:
1506 * this only checks ranges, and does not
1507 * check for invalid codepoints
1509 if (c < 0x80) {
1510 count += 1;
1511 } else if (c < 0x800) {
1512 count += 2;
1513 } else if (c < 0x1000) {
1514 count += 3;
1515 } else {
1516 count += 4;
1518 break;
1519 default:
1521 * non-unicode encoding:
1522 * assume that each codepoint fits into
1523 * one unit in the destination encoding.
1525 count += 1;
1529 return count;
1532 size_t strlen_m_ext_term(const char *s, const charset_t src_charset,
1533 const charset_t dst_charset)
1535 if (!s) {
1536 return 0;
1538 return strlen_m_ext(s, src_charset, dst_charset) + 1;
1542 * Calculate the number of 16-bit units that would bee needed to convert
1543 * the input string which is expected to be in CH_UNIX encoding to UTF16.
1545 * This will be the same as the number of bytes in a string for single
1546 * byte strings, but will be different for multibyte.
1549 size_t strlen_m(const char *s)
1551 return strlen_m_ext(s, CH_UNIX, CH_UTF16LE);
1555 Count the number of UCS2 characters in a string including the null
1556 terminator.
1559 size_t strlen_m_term(const char *s)
1561 if (!s) {
1562 return 0;
1564 return strlen_m(s) + 1;
1568 * Weird helper routine for the winreg pipe: If nothing is around, return 0,
1569 * if a string is there, include the terminator.
1572 size_t strlen_m_term_null(const char *s)
1574 size_t len;
1575 if (!s) {
1576 return 0;
1578 len = strlen_m(s);
1579 if (len == 0) {
1580 return 0;
1583 return len+1;
1587 Just a typesafety wrapper for snprintf into a fstring.
1590 int fstr_sprintf(fstring s, const char *fmt, ...)
1592 va_list ap;
1593 int ret;
1595 va_start(ap, fmt);
1596 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1597 va_end(ap);
1598 return ret;
1602 List of Strings manipulation functions
1605 #define S_LIST_ABS 16 /* List Allocation Block Size */
1607 /******************************************************************************
1608 version of standard_sub_basic() for string lists; uses talloc_sub_basic()
1609 for the work
1610 *****************************************************************************/
1612 bool str_list_sub_basic( char **list, const char *smb_name,
1613 const char *domain_name )
1615 TALLOC_CTX *ctx = list;
1616 char *s, *tmpstr;
1618 while ( *list ) {
1619 s = *list;
1620 tmpstr = talloc_sub_basic(ctx, smb_name, domain_name, s);
1621 if ( !tmpstr ) {
1622 DEBUG(0,("str_list_sub_basic: "
1623 "alloc_sub_basic() return NULL!\n"));
1624 return false;
1627 TALLOC_FREE(*list);
1628 *list = tmpstr;
1630 list++;
1633 return true;
1636 /******************************************************************************
1637 substitute a specific pattern in a string list
1638 *****************************************************************************/
1640 bool str_list_substitute(char **list, const char *pattern, const char *insert)
1642 TALLOC_CTX *ctx = list;
1643 char *p, *s, *t;
1644 ssize_t ls, lp, li, ld, i, d;
1646 if (!list)
1647 return false;
1648 if (!pattern)
1649 return false;
1650 if (!insert)
1651 return false;
1653 lp = (ssize_t)strlen(pattern);
1654 li = (ssize_t)strlen(insert);
1655 ld = li -lp;
1657 while (*list) {
1658 s = *list;
1659 ls = (ssize_t)strlen(s);
1661 while ((p = strstr_m(s, pattern))) {
1662 t = *list;
1663 d = p -t;
1664 if (ld) {
1665 t = TALLOC_ARRAY(ctx, char, ls +ld +1);
1666 if (!t) {
1667 DEBUG(0,("str_list_substitute: "
1668 "Unable to allocate memory"));
1669 return false;
1671 memcpy(t, *list, d);
1672 memcpy(t +d +li, p +lp, ls -d -lp +1);
1673 TALLOC_FREE(*list);
1674 *list = t;
1675 ls += ld;
1676 s = t +d +li;
1679 for (i = 0; i < li; i++) {
1680 switch (insert[i]) {
1681 case '`':
1682 case '"':
1683 case '\'':
1684 case ';':
1685 case '$':
1686 case '%':
1687 case '\r':
1688 case '\n':
1689 t[d +i] = '_';
1690 break;
1691 default:
1692 t[d +i] = insert[i];
1697 list++;
1700 return true;
1704 #define IPSTR_LIST_SEP ","
1705 #define IPSTR_LIST_CHAR ','
1708 * Add ip string representation to ipstr list. Used also
1709 * as part of @function ipstr_list_make
1711 * @param ipstr_list pointer to string containing ip list;
1712 * MUST BE already allocated and IS reallocated if necessary
1713 * @param ipstr_size pointer to current size of ipstr_list (might be changed
1714 * as a result of reallocation)
1715 * @param ip IP address which is to be added to list
1716 * @return pointer to string appended with new ip and possibly
1717 * reallocated to new length
1720 static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service)
1722 char *new_ipstr = NULL;
1723 char addr_buf[INET6_ADDRSTRLEN];
1724 int ret;
1726 /* arguments checking */
1727 if (!ipstr_list || !service) {
1728 return NULL;
1731 print_sockaddr(addr_buf,
1732 sizeof(addr_buf),
1733 &service->ss);
1735 /* attempt to convert ip to a string and append colon separator to it */
1736 if (*ipstr_list) {
1737 if (service->ss.ss_family == AF_INET) {
1738 /* IPv4 */
1739 ret = asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list,
1740 IPSTR_LIST_SEP, addr_buf,
1741 service->port);
1742 } else {
1743 /* IPv6 */
1744 ret = asprintf(&new_ipstr, "%s%s[%s]:%d", *ipstr_list,
1745 IPSTR_LIST_SEP, addr_buf,
1746 service->port);
1748 SAFE_FREE(*ipstr_list);
1749 } else {
1750 if (service->ss.ss_family == AF_INET) {
1751 /* IPv4 */
1752 ret = asprintf(&new_ipstr, "%s:%d", addr_buf,
1753 service->port);
1754 } else {
1755 /* IPv6 */
1756 ret = asprintf(&new_ipstr, "[%s]:%d", addr_buf,
1757 service->port);
1760 if (ret == -1) {
1761 return NULL;
1763 *ipstr_list = new_ipstr;
1764 return *ipstr_list;
1768 * Allocate and initialise an ipstr list using ip adresses
1769 * passed as arguments.
1771 * @param ipstr_list pointer to string meant to be allocated and set
1772 * @param ip_list array of ip addresses to place in the list
1773 * @param ip_count number of addresses stored in ip_list
1774 * @return pointer to allocated ip string
1777 char *ipstr_list_make(char **ipstr_list,
1778 const struct ip_service *ip_list,
1779 int ip_count)
1781 int i;
1783 /* arguments checking */
1784 if (!ip_list || !ipstr_list) {
1785 return 0;
1788 *ipstr_list = NULL;
1790 /* process ip addresses given as arguments */
1791 for (i = 0; i < ip_count; i++) {
1792 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1795 return (*ipstr_list);
1800 * Parse given ip string list into array of ip addresses
1801 * (as ip_service structures)
1802 * e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
1804 * @param ipstr ip string list to be parsed
1805 * @param ip_list pointer to array of ip addresses which is
1806 * allocated by this function and must be freed by caller
1807 * @return number of successfully parsed addresses
1810 int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list)
1812 TALLOC_CTX *frame;
1813 char *token_str = NULL;
1814 size_t count;
1815 int i;
1817 if (!ipstr_list || !ip_list)
1818 return 0;
1820 count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1821 if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
1822 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n",
1823 (unsigned long)count));
1824 return 0;
1827 frame = talloc_stackframe();
1828 for ( i=0; next_token_talloc(frame, &ipstr_list, &token_str,
1829 IPSTR_LIST_SEP) && i<count; i++ ) {
1830 char *s = token_str;
1831 char *p = strrchr(token_str, ':');
1833 if (p) {
1834 *p = 0;
1835 (*ip_list)[i].port = atoi(p+1);
1838 /* convert single token to ip address */
1839 if (token_str[0] == '[') {
1840 /* IPv6 address. */
1841 s++;
1842 p = strchr(token_str, ']');
1843 if (!p) {
1844 continue;
1846 *p = '\0';
1848 if (!interpret_string_addr(&(*ip_list)[i].ss,
1850 AI_NUMERICHOST)) {
1851 continue;
1854 TALLOC_FREE(frame);
1855 return count;
1859 * Safely free ip string list
1861 * @param ipstr_list ip string list to be freed
1864 void ipstr_list_free(char* ipstr_list)
1866 SAFE_FREE(ipstr_list);
1869 static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1872 * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
1874 DATA_BLOB base64_decode_data_blob(const char *s)
1876 int bit_offset, byte_offset, idx, i, n;
1877 DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1878 unsigned char *d = decoded.data;
1879 char *p;
1881 n=i=0;
1883 while (*s && (p=strchr_m(b64,*s))) {
1884 idx = (int)(p - b64);
1885 byte_offset = (i*6)/8;
1886 bit_offset = (i*6)%8;
1887 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1888 if (bit_offset < 3) {
1889 d[byte_offset] |= (idx << (2-bit_offset));
1890 n = byte_offset+1;
1891 } else {
1892 d[byte_offset] |= (idx >> (bit_offset-2));
1893 d[byte_offset+1] = 0;
1894 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1895 n = byte_offset+2;
1897 s++; i++;
1900 if ((n > 0) && (*s == '=')) {
1901 n -= 1;
1904 /* fix up length */
1905 decoded.length = n;
1906 return decoded;
1910 * Decode a base64 string in-place - wrapper for the above
1912 void base64_decode_inplace(char *s)
1914 DATA_BLOB decoded = base64_decode_data_blob(s);
1916 if ( decoded.length != 0 ) {
1917 memcpy(s, decoded.data, decoded.length);
1919 /* null terminate */
1920 s[decoded.length] = '\0';
1921 } else {
1922 *s = '\0';
1925 data_blob_free(&decoded);
1929 * Encode a base64 string into a talloc()ed string caller to free.
1931 * From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c
1932 * with adjustments
1935 char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
1937 int bits = 0;
1938 int char_count = 0;
1939 size_t out_cnt, len, output_len;
1940 char *result;
1942 if (!data.length || !data.data)
1943 return NULL;
1945 out_cnt = 0;
1946 len = data.length;
1947 output_len = data.length * 2 + 4; /* Account for closing bytes. 4 is
1948 * random but should be enough for
1949 * the = and \0 */
1950 result = TALLOC_ARRAY(mem_ctx, char, output_len); /* get us plenty of space */
1951 SMB_ASSERT(result != NULL);
1953 while (len--) {
1954 int c = (unsigned char) *(data.data++);
1955 bits += c;
1956 char_count++;
1957 if (char_count == 3) {
1958 result[out_cnt++] = b64[bits >> 18];
1959 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1960 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1961 result[out_cnt++] = b64[bits & 0x3f];
1962 bits = 0;
1963 char_count = 0;
1964 } else {
1965 bits <<= 8;
1968 if (char_count != 0) {
1969 bits <<= 16 - (8 * char_count);
1970 result[out_cnt++] = b64[bits >> 18];
1971 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1972 if (char_count == 1) {
1973 result[out_cnt++] = '=';
1974 result[out_cnt++] = '=';
1975 } else {
1976 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1977 result[out_cnt++] = '=';
1980 result[out_cnt] = '\0'; /* terminate */
1981 return result;
1984 /* read a SMB_BIG_UINT from a string */
1985 uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1988 uint64_t val = (uint64_t)-1;
1989 const char *p = nptr;
1991 if (!p) {
1992 if (entptr) {
1993 *entptr = p;
1995 return val;
1998 while (*p && isspace(*p))
1999 p++;
2001 sscanf(p,"%"PRIu64,&val);
2002 if (entptr) {
2003 while (*p && isdigit(*p))
2004 p++;
2005 *entptr = p;
2008 return val;
2011 /* Convert a size specification to a count of bytes. We accept the following
2012 * suffixes:
2013 * bytes if there is no suffix
2014 * kK kibibytes
2015 * mM mebibytes
2016 * gG gibibytes
2017 * tT tibibytes
2018 * pP whatever the ISO name for petabytes is
2020 * Returns 0 if the string can't be converted.
2022 SMB_OFF_T conv_str_size(const char * str)
2024 SMB_OFF_T lval_orig;
2025 SMB_OFF_T lval;
2026 char * end;
2028 if (str == NULL || *str == '\0') {
2029 return 0;
2032 #ifdef HAVE_STRTOULL
2033 if (sizeof(SMB_OFF_T) == 8) {
2034 lval = strtoull(str, &end, 10 /* base */);
2035 } else {
2036 lval = strtoul(str, &end, 10 /* base */);
2038 #else
2039 lval = strtoul(str, &end, 10 /* base */);
2040 #endif
2042 if (end == NULL || end == str) {
2043 return 0;
2046 if (*end == '\0') {
2047 return lval;
2050 lval_orig = lval;
2052 if (strwicmp(end, "K") == 0) {
2053 lval *= (SMB_OFF_T)1024;
2054 } else if (strwicmp(end, "M") == 0) {
2055 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2056 } else if (strwicmp(end, "G") == 0) {
2057 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2058 (SMB_OFF_T)1024);
2059 } else if (strwicmp(end, "T") == 0) {
2060 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2061 (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2062 } else if (strwicmp(end, "P") == 0) {
2063 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2064 (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2065 (SMB_OFF_T)1024);
2066 } else {
2067 return 0;
2071 * Primitive attempt to detect wrapping on platforms with
2072 * 4-byte SMB_OFF_T. It's better to let the caller handle a
2073 * failure than some random number.
2075 if (lval_orig <= lval) {
2076 return 0;
2079 return lval;
2082 void string_append(char **left, const char *right)
2084 int new_len = strlen(right) + 1;
2086 if (*left == NULL) {
2087 *left = (char *)SMB_MALLOC(new_len);
2088 if (*left == NULL) {
2089 return;
2091 *left[0] = '\0';
2092 } else {
2093 new_len += strlen(*left);
2094 *left = (char *)SMB_REALLOC(*left, new_len);
2097 if (*left == NULL) {
2098 return;
2101 safe_strcat(*left, right, new_len-1);
2104 bool add_string_to_array(TALLOC_CTX *mem_ctx,
2105 const char *str, const char ***strings,
2106 int *num)
2108 char *dup_str = talloc_strdup(mem_ctx, str);
2110 *strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings,
2111 const char *, (*num)+1);
2113 if ((*strings == NULL) || (dup_str == NULL)) {
2114 *num = 0;
2115 return false;
2118 (*strings)[*num] = dup_str;
2119 *num += 1;
2120 return true;
2123 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
2124 * error checking in between. The indiation that something weird happened is
2125 * string==NULL */
2127 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
2128 size_t *bufsize, const char *fmt, ...)
2130 va_list ap;
2131 char *newstr;
2132 int ret;
2133 bool increased;
2135 /* len<0 is an internal marker that something failed */
2136 if (*len < 0)
2137 goto error;
2139 if (*string == NULL) {
2140 if (*bufsize == 0)
2141 *bufsize = 128;
2143 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
2144 if (*string == NULL)
2145 goto error;
2148 va_start(ap, fmt);
2149 ret = vasprintf(&newstr, fmt, ap);
2150 va_end(ap);
2152 if (ret < 0)
2153 goto error;
2155 increased = false;
2157 while ((*len)+ret >= *bufsize) {
2158 increased = true;
2159 *bufsize *= 2;
2160 if (*bufsize >= (1024*1024*256))
2161 goto error;
2164 if (increased) {
2165 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
2166 *bufsize);
2167 if (*string == NULL) {
2168 goto error;
2172 StrnCpy((*string)+(*len), newstr, ret);
2173 (*len) += ret;
2174 free(newstr);
2175 return;
2177 error:
2178 *len = -1;
2179 *string = NULL;
2183 * asprintf into a string and strupper_m it after that.
2186 int asprintf_strupper_m(char **strp, const char *fmt, ...)
2188 va_list ap;
2189 char *result;
2190 int ret;
2192 va_start(ap, fmt);
2193 ret = vasprintf(&result, fmt, ap);
2194 va_end(ap);
2196 if (ret == -1)
2197 return -1;
2199 strupper_m(result);
2200 *strp = result;
2201 return ret;
2204 char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
2206 va_list ap;
2207 char *ret;
2209 va_start(ap, fmt);
2210 ret = talloc_vasprintf(t, fmt, ap);
2211 va_end(ap);
2213 if (ret == NULL) {
2214 return NULL;
2216 strupper_m(ret);
2217 return ret;
2220 char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
2222 va_list ap;
2223 char *ret;
2225 va_start(ap, fmt);
2226 ret = talloc_vasprintf(t, fmt, ap);
2227 va_end(ap);
2229 if (ret == NULL) {
2230 return NULL;
2232 strlower_m(ret);
2233 return ret;
2238 Returns the substring from src between the first occurrence of
2239 the char "front" and the first occurence of the char "back".
2240 Mallocs the return string which must be freed. Not for use
2241 with wide character strings.
2243 char *sstring_sub(const char *src, char front, char back)
2245 char *temp1, *temp2, *temp3;
2246 ptrdiff_t len;
2248 temp1 = strchr(src, front);
2249 if (temp1 == NULL) return NULL;
2250 temp2 = strchr(src, back);
2251 if (temp2 == NULL) return NULL;
2252 len = temp2 - temp1;
2253 if (len <= 0) return NULL;
2254 temp3 = (char*)SMB_MALLOC(len);
2255 if (temp3 == NULL) {
2256 DEBUG(1,("Malloc failure in sstring_sub\n"));
2257 return NULL;
2259 memcpy(temp3, temp1+1, len-1);
2260 temp3[len-1] = '\0';
2261 return temp3;
2264 /********************************************************************
2265 Check a string for any occurrences of a specified list of invalid
2266 characters.
2267 ********************************************************************/
2269 bool validate_net_name( const char *name,
2270 const char *invalid_chars,
2271 int max_len)
2273 int i;
2275 if (!name) {
2276 return false;
2279 for ( i=0; i<max_len && name[i]; i++ ) {
2280 /* fail if strchr_m() finds one of the invalid characters */
2281 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
2282 return false;
2286 return true;
2290 /*******************************************************************
2291 Add a shell escape character '\' to any character not in a known list
2292 of characters. UNIX charset format.
2293 *******************************************************************/
2295 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
2296 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
2298 char *escape_shell_string(const char *src)
2300 size_t srclen = strlen(src);
2301 char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
2302 char *dest = ret;
2303 bool in_s_quote = false;
2304 bool in_d_quote = false;
2305 bool next_escaped = false;
2307 if (!ret) {
2308 return NULL;
2311 while (*src) {
2312 size_t c_size;
2313 codepoint_t c = next_codepoint(src, &c_size);
2315 if (c == INVALID_CODEPOINT) {
2316 SAFE_FREE(ret);
2317 return NULL;
2320 if (c_size > 1) {
2321 memcpy(dest, src, c_size);
2322 src += c_size;
2323 dest += c_size;
2324 next_escaped = false;
2325 continue;
2329 * Deal with backslash escaped state.
2330 * This only lasts for one character.
2333 if (next_escaped) {
2334 *dest++ = *src++;
2335 next_escaped = false;
2336 continue;
2340 * Deal with single quote state. The
2341 * only thing we care about is exiting
2342 * this state.
2345 if (in_s_quote) {
2346 if (*src == '\'') {
2347 in_s_quote = false;
2349 *dest++ = *src++;
2350 continue;
2354 * Deal with double quote state. The most
2355 * complex state. We must cope with \, meaning
2356 * possibly escape next char (depending what it
2357 * is), ", meaning exit this state, and possibly
2358 * add an \ escape to any unprotected character
2359 * (listed in INSIDE_DQUOTE_LIST).
2362 if (in_d_quote) {
2363 if (*src == '\\') {
2365 * Next character might be escaped.
2366 * We have to peek. Inside double
2367 * quotes only INSIDE_DQUOTE_LIST
2368 * characters are escaped by a \.
2371 char nextchar;
2373 c = next_codepoint(&src[1], &c_size);
2374 if (c == INVALID_CODEPOINT) {
2375 SAFE_FREE(ret);
2376 return NULL;
2378 if (c_size > 1) {
2380 * Don't escape the next char.
2381 * Just copy the \.
2383 *dest++ = *src++;
2384 continue;
2387 nextchar = src[1];
2389 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
2390 (int)nextchar)) {
2391 next_escaped = true;
2393 *dest++ = *src++;
2394 continue;
2397 if (*src == '\"') {
2398 /* Exit double quote state. */
2399 in_d_quote = false;
2400 *dest++ = *src++;
2401 continue;
2405 * We know the character isn't \ or ",
2406 * so escape it if it's any of the other
2407 * possible unprotected characters.
2410 if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
2411 *dest++ = '\\';
2413 *dest++ = *src++;
2414 continue;
2418 * From here to the end of the loop we're
2419 * not in the single or double quote state.
2422 if (*src == '\\') {
2423 /* Next character must be escaped. */
2424 next_escaped = true;
2425 *dest++ = *src++;
2426 continue;
2429 if (*src == '\'') {
2430 /* Go into single quote state. */
2431 in_s_quote = true;
2432 *dest++ = *src++;
2433 continue;
2436 if (*src == '\"') {
2437 /* Go into double quote state. */
2438 in_d_quote = true;
2439 *dest++ = *src++;
2440 continue;
2443 /* Check if we need to escape the character. */
2445 if (!strchr(INCLUDE_LIST, (int)*src)) {
2446 *dest++ = '\\';
2448 *dest++ = *src++;
2450 *dest++ = '\0';
2451 return ret;
2454 /***************************************************
2455 str_list_make, v3 version. The v4 version does not
2456 look at quoted strings with embedded blanks, so
2457 do NOT merge this function please!
2458 ***************************************************/
2460 #define S_LIST_ABS 16 /* List Allocation Block Size */
2462 char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
2463 const char *sep)
2465 char **list;
2466 const char *str;
2467 char *s, *tok;
2468 int num, lsize;
2470 if (!string || !*string)
2471 return NULL;
2473 list = TALLOC_ARRAY(mem_ctx, char *, S_LIST_ABS+1);
2474 if (list == NULL) {
2475 return NULL;
2477 lsize = S_LIST_ABS;
2479 s = talloc_strdup(list, string);
2480 if (s == NULL) {
2481 DEBUG(0,("str_list_make: Unable to allocate memory"));
2482 TALLOC_FREE(list);
2483 return NULL;
2485 if (!sep) sep = LIST_SEP;
2487 num = 0;
2488 str = s;
2490 while (next_token_talloc(list, &str, &tok, sep)) {
2492 if (num == lsize) {
2493 char **tmp;
2495 lsize += S_LIST_ABS;
2497 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *,
2498 lsize + 1);
2499 if (tmp == NULL) {
2500 DEBUG(0,("str_list_make: "
2501 "Unable to allocate memory"));
2502 TALLOC_FREE(list);
2503 return NULL;
2506 list = tmp;
2508 memset (&list[num], 0,
2509 ((sizeof(char**)) * (S_LIST_ABS +1)));
2512 list[num] = tok;
2513 num += 1;
2516 list[num] = NULL;
2518 TALLOC_FREE(s);
2519 return list;
2522 char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
2524 fstring tmp;
2526 alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
2527 return talloc_strdup(mem_ctx, tmp);