Added Andrew Bartlett's patch to use an allocated buffer for count_chars.
[Samba/bb.git] / source3 / lib / util_str.c
blobcde6b2e7a1728fadeb127efea896d3f886f610c0
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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 /**
27 * @file
28 * @brief String utilities.
29 **/
31 /**
32 * Get the next token from a string, return False if none found.
33 * Handles double-quotes.
35 * Based on a routine by GJC@VILLAGE.COM.
36 * Extensively modified by Andrew.Tridgell@anu.edu.au
37 **/
38 BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
40 char *s;
41 char *pbuf;
42 BOOL quoted;
43 size_t len=1;
45 if (!ptr)
46 return(False);
48 s = (char *)*ptr;
50 /* default to simple separators */
51 if (!sep)
52 sep = " \t\n\r";
54 /* find the first non sep char */
55 while (*s && strchr_m(sep,*s))
56 s++;
58 /* nothing left? */
59 if (! *s)
60 return(False);
62 /* copy over the token */
63 pbuf = buff;
64 for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
65 if (*s == '\"' || *s == '\'') {
66 quoted = !quoted;
67 } else {
68 len++;
69 *pbuf++ = *s;
73 *ptr = (*s) ? s+1 : s;
74 *pbuf = 0;
76 return(True);
79 /**
80 This is like next_token but is not re-entrant and "remembers" the first
81 parameter so you can pass NULL. This is useful for user interface code
82 but beware the fact that it is not re-entrant!
83 **/
85 static const char *last_ptr=NULL;
87 BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
89 BOOL ret;
90 if (!ptr)
91 ptr = &last_ptr;
93 ret = next_token(ptr, buff, sep, bufsize);
94 last_ptr = *ptr;
95 return ret;
98 static uint16 tmpbuf[sizeof(pstring)];
100 void set_first_token(char *ptr)
102 last_ptr = ptr;
106 Convert list of tokens to array; dependent on above routine.
107 Uses last_ptr from above - bit of a hack.
110 char **toktocliplist(int *ctok, const char *sep)
112 char *s=(char *)last_ptr;
113 int ictok=0;
114 char **ret, **iret;
116 if (!sep)
117 sep = " \t\n\r";
119 while(*s && strchr_m(sep,*s))
120 s++;
122 /* nothing left? */
123 if (!*s)
124 return(NULL);
126 do {
127 ictok++;
128 while(*s && (!strchr_m(sep,*s)))
129 s++;
130 while(*s && strchr_m(sep,*s))
131 *s++=0;
132 } while(*s);
134 *ctok=ictok;
135 s=(char *)last_ptr;
137 if (!(ret=iret=malloc(ictok*sizeof(char *))))
138 return NULL;
140 while(ictok--) {
141 *iret++=s;
142 while(*s++)
144 while(!*s)
145 s++;
148 return ret;
152 * Case insensitive string compararison.
154 * iconv does not directly give us a way to compare strings in
155 * arbitrary unix character sets -- all we can is convert and then
156 * compare. This is expensive.
158 * As an optimization, we do a first pass that considers only the
159 * prefix of the strings that is entirely 7-bit. Within this, we
160 * check whether they have the same value.
162 * Hopefully this will often give the answer without needing to copy.
163 * In particular it should speed comparisons to literal ascii strings
164 * or comparisons of strings that are "obviously" different.
166 * If we find a non-ascii character we fall back to converting via
167 * iconv.
169 * This should never be slower than convering the whole thing, and
170 * often faster.
172 * A different optimization would be to compare for bitwise equality
173 * in the binary encoding. (It would be possible thought hairy to do
174 * both simultaneously.) But in that case if they turn out to be
175 * different, we'd need to restart the whole thing.
177 * Even better is to implement strcasecmp for each encoding and use a
178 * function pointer.
180 int StrCaseCmp(const char *s, const char *t)
183 const char * ps, * pt;
184 size_t size;
185 smb_ucs2_t *buffer_s, *buffer_t;
186 int ret;
188 for (ps = s, pt = t; ; ps++, pt++) {
189 char us, ut;
191 if (!*ps && !*pt)
192 return 0; /* both ended */
193 else if (!*ps)
194 return -1; /* s is a prefix */
195 else if (!*pt)
196 return +1; /* t is a prefix */
197 else if ((*ps & 0x80) || (*pt & 0x80))
198 /* not ascii anymore, do it the hard way from here on in */
199 break;
201 us = toupper(*ps);
202 ut = toupper(*pt);
203 if (us == ut)
204 continue;
205 else if (us < ut)
206 return -1;
207 else if (us > ut)
208 return +1;
211 size = push_ucs2_allocate(&buffer_s, s);
212 if (size == (size_t)-1) {
213 return strcmp(s, t);
214 /* Not quite the right answer, but finding the right one
215 under this failure case is expensive, and it's pretty close */
218 size = push_ucs2_allocate(&buffer_t, t);
219 if (size == (size_t)-1) {
220 SAFE_FREE(buffer_s);
221 return strcmp(s, t);
222 /* Not quite the right answer, but finding the right one
223 under this failure case is expensive, and it's pretty close */
226 ret = strcasecmp_w(buffer_s, buffer_t);
227 SAFE_FREE(buffer_s);
228 SAFE_FREE(buffer_t);
229 return ret;
234 Case insensitive string compararison, length limited.
236 int StrnCaseCmp(const char *s, const char *t, size_t n)
238 pstring buf1, buf2;
239 unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
240 unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
241 return strncmp(buf1,buf2,n);
245 * Compare 2 strings.
247 * @note The comparison is case-insensitive.
249 BOOL strequal(const char *s1, const char *s2)
251 if (s1 == s2)
252 return(True);
253 if (!s1 || !s2)
254 return(False);
256 return(StrCaseCmp(s1,s2)==0);
260 * Compare 2 strings up to and including the nth char.
262 * @note The comparison is case-insensitive.
264 BOOL strnequal(const char *s1,const char *s2,size_t n)
266 if (s1 == s2)
267 return(True);
268 if (!s1 || !s2 || !n)
269 return(False);
271 return(StrnCaseCmp(s1,s2,n)==0);
275 Compare 2 strings (case sensitive).
278 BOOL strcsequal(const char *s1,const char *s2)
280 if (s1 == s2)
281 return(True);
282 if (!s1 || !s2)
283 return(False);
285 return(strcmp(s1,s2)==0);
289 Do a case-insensitive, whitespace-ignoring string compare.
292 int strwicmp(const char *psz1, const char *psz2)
294 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
295 /* appropriate value. */
296 if (psz1 == psz2)
297 return (0);
298 else if (psz1 == NULL)
299 return (-1);
300 else if (psz2 == NULL)
301 return (1);
303 /* sync the strings on first non-whitespace */
304 while (1) {
305 while (isspace((int)*psz1))
306 psz1++;
307 while (isspace((int)*psz2))
308 psz2++;
309 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
310 || *psz2 == '\0')
311 break;
312 psz1++;
313 psz2++;
315 return (*psz1 - *psz2);
320 Convert a string to upper case, but don't modify it.
323 char *strupper_static(const char *s)
325 static pstring str;
327 pstrcpy(str, s);
328 strupper_m(str);
330 return str;
334 Convert a string to "normal" form.
337 void strnorm(char *s)
339 extern int case_default;
340 if (case_default == CASE_UPPER)
341 strupper_m(s);
342 else
343 strlower_m(s);
347 Check if a string is in "normal" case.
350 BOOL strisnormal(const char *s)
352 extern int case_default;
353 if (case_default == CASE_UPPER)
354 return(!strhaslower(s));
356 return(!strhasupper(s));
361 String replace.
362 NOTE: oldc and newc must be 7 bit characters
365 void string_replace(pstring s,char oldc,char newc)
367 unsigned char *p;
369 /* this is quite a common operation, so we want it to be
370 fast. We optimise for the ascii case, knowing that all our
371 supported multi-byte character sets are ascii-compatible
372 (ie. they match for the first 128 chars) */
374 for (p = (unsigned char *)s; *p; p++) {
375 if (*p & 0x80) /* mb string - slow path. */
376 break;
377 if (*p == oldc)
378 *p = newc;
381 if (!*p)
382 return;
384 /* Slow (mb) path. */
385 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
386 /* With compose characters we must restart from the beginning. JRA. */
387 p = s;
388 #endif
389 push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE);
390 string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
391 pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
395 Skip past some strings in a buffer.
398 char *skip_string(char *buf,size_t n)
400 while (n--)
401 buf += strlen(buf) + 1;
402 return(buf);
406 Count the number of characters in a string. Normally this will
407 be the same as the number of bytes in a string for single byte strings,
408 but will be different for multibyte.
411 size_t str_charnum(const char *s)
413 uint16 tmpbuf2[sizeof(pstring)];
414 push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
415 return strlen_w(tmpbuf2);
419 Count the number of characters in a string. Normally this will
420 be the same as the number of bytes in a string for single byte strings,
421 but will be different for multibyte.
424 size_t str_ascii_charnum(const char *s)
426 pstring tmpbuf2;
427 push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
428 return strlen(tmpbuf2);
431 BOOL trim_char(char *s,char cfront,char cback)
433 BOOL ret = False;
434 char *ep;
435 char *fp = s;
437 /* Ignore null or empty strings. */
438 if (!s || (s[0] == '\0'))
439 return False;
441 if (cfront) {
442 while (*fp && *fp == cfront)
443 fp++;
444 if (!*fp) {
445 /* We ate the string. */
446 s[0] = '\0';
447 return True;
449 if (fp != s)
450 ret = True;
453 ep = fp + strlen(fp) - 1;
454 if (cback) {
455 /* Attempt ascii only. Bail for mb strings. */
456 while ((ep >= fp) && (*ep == cback)) {
457 ret = True;
458 if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
459 /* Could be mb... bail back to tim_string. */
460 char fs[2], bs[2];
461 if (cfront) {
462 fs[0] = cfront;
463 fs[1] = '\0';
465 bs[0] = cback;
466 bs[1] = '\0';
467 return trim_string(s, cfront ? fs : NULL, bs);
468 } else {
469 ep--;
472 if (ep < fp) {
473 /* We ate the string. */
474 s[0] = '\0';
475 return True;
479 ep[1] = '\0';
480 memmove(s, fp, ep-fp+2);
481 return ret;
485 Trim the specified elements off the front and back of a string.
488 BOOL trim_string(char *s,const char *front,const char *back)
490 BOOL ret = False;
491 size_t front_len;
492 size_t back_len;
493 size_t len;
495 /* Ignore null or empty strings. */
496 if (!s || (s[0] == '\0'))
497 return False;
499 front_len = front? strlen(front) : 0;
500 back_len = back? strlen(back) : 0;
502 len = strlen(s);
504 if (front_len) {
505 while (len && strncmp(s, front, front_len)==0) {
506 /* Must use memmove here as src & dest can
507 * easily overlap. Found by valgrind. JRA. */
508 memmove(s, s+front_len, (len-front_len)+1);
509 len -= front_len;
510 ret=True;
514 if (back_len) {
515 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
516 s[len-back_len]='\0';
517 len -= back_len;
518 ret=True;
521 return ret;
525 Does a string have any uppercase chars in it?
528 BOOL strhasupper(const char *s)
530 smb_ucs2_t *ptr;
531 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
532 for(ptr=tmpbuf;*ptr;ptr++)
533 if(isupper_w(*ptr))
534 return True;
535 return(False);
539 Does a string have any lowercase chars in it?
542 BOOL strhaslower(const char *s)
544 smb_ucs2_t *ptr;
545 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
546 for(ptr=tmpbuf;*ptr;ptr++)
547 if(islower_w(*ptr))
548 return True;
549 return(False);
553 Find the number of 'c' chars in a string
556 size_t count_chars(const char *s,char c)
558 smb_ucs2_t *ptr;
559 int count;
560 smb_ucs2_t *alloc_tmpbuf;
562 if (push_ucs2_allocate(&alloc_tmpbuf, s) == (size_t)-1) {
563 return 0;
566 for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++)
567 if(*ptr==UCS2_CHAR(c))
568 count++;
570 return(count);
574 Safe string copy into a known length string. maxlength does not
575 include the terminating zero.
578 char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_t maxlength)
580 size_t len;
582 if (!dest) {
583 DEBUG(0,("ERROR: NULL dest in safe_strcpy, called from [%s][%d]\n", fn, line));
584 return NULL;
587 #ifdef DEVELOPER
588 clobber_region(fn,line,dest, maxlength+1);
589 #endif
591 if (!src) {
592 *dest = 0;
593 return dest;
596 len = strnlen(src, maxlength+1);
598 if (len > maxlength) {
599 DEBUG(0,("ERROR: string overflow by %lu (%lu - %lu) in safe_strcpy [%.50s]\n",
600 (unsigned long)(len-maxlength), (unsigned long)len,
601 (unsigned long)maxlength, src));
602 len = maxlength;
605 memmove(dest, src, len);
606 dest[len] = 0;
607 return dest;
611 Safe string cat into a string. maxlength does not
612 include the terminating zero.
614 char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
616 size_t src_len, dest_len;
618 if (!dest) {
619 DEBUG(0,("ERROR: NULL dest in safe_strcat, called from [%s][%d]\n", fn, line));
620 return NULL;
623 if (!src)
624 return dest;
626 src_len = strnlen(src, maxlength + 1);
627 dest_len = strnlen(dest, maxlength + 1);
629 #ifdef DEVELOPER
630 clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
631 #endif
633 if (src_len + dest_len > maxlength) {
634 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
635 (int)(src_len + dest_len - maxlength), src));
636 if (maxlength > dest_len) {
637 memcpy(&dest[dest_len], src, maxlength - dest_len);
639 dest[maxlength] = 0;
640 return NULL;
643 memcpy(&dest[dest_len], src, src_len);
644 dest[dest_len + src_len] = 0;
645 return dest;
649 Paranoid strcpy into a buffer of given length (includes terminating
650 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
651 and replaces with '_'. Deliberately does *NOT* check for multibyte
652 characters. Don't change it !
654 char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
656 size_t len, i;
658 #ifdef DEVELOPER
659 clobber_region(fn, line, dest, maxlength);
660 #endif
662 if (!dest) {
663 DEBUG(0,("ERROR: NULL dest in alpha_strcpy, called from [%s][%d]\n", fn, line));
664 return NULL;
667 if (!src) {
668 *dest = 0;
669 return dest;
672 len = strlen(src);
673 if (len >= maxlength)
674 len = maxlength - 1;
676 if (!other_safe_chars)
677 other_safe_chars = "";
679 for(i = 0; i < len; i++) {
680 int val = (src[i] & 0xff);
681 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
682 dest[i] = src[i];
683 else
684 dest[i] = '_';
687 dest[i] = '\0';
689 return dest;
693 Like strncpy but always null terminates. Make sure there is room!
694 The variable n should always be one less than the available size.
696 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
698 char *d = dest;
700 #ifdef DEVELOPER
701 clobber_region(fn, line, dest, n+1);
702 #endif
704 if (!dest) {
705 DEBUG(0,("ERROR: NULL dest in StrnCpy, called from [%s][%d]\n", fn, line));
706 return(NULL);
709 if (!src) {
710 *dest = 0;
711 return(dest);
714 while (n-- && (*d = *src)) {
715 d++;
716 src++;
719 *d = 0;
720 return(dest);
723 #if 0
725 Like strncpy but copies up to the character marker. always null terminates.
726 returns a pointer to the character marker in the source string (src).
729 static char *strncpyn(char *dest, const char *src, size_t n, char c)
731 char *p;
732 size_t str_len;
734 #ifdef DEVELOPER
735 clobber_region(dest, n+1);
736 #endif
737 p = strchr_m(src, c);
738 if (p == NULL) {
739 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
740 return NULL;
743 str_len = PTR_DIFF(p, src);
744 strncpy(dest, src, MIN(n, str_len));
745 dest[str_len] = '\0';
747 return p;
749 #endif
752 Routine to get hex characters and turn them into a 16 byte array.
753 the array can be variable length, and any non-hex-numeric
754 characters are skipped. "0xnn" or "0Xnn" is specially catered
755 for.
757 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
761 size_t strhex_to_str(char *p, size_t len, const char *strhex)
763 size_t i;
764 size_t num_chars = 0;
765 unsigned char lonybble, hinybble;
766 const char *hexchars = "0123456789ABCDEF";
767 char *p1 = NULL, *p2 = NULL;
769 for (i = 0; i < len && strhex[i] != 0; i++) {
770 if (strnequal(hexchars, "0x", 2)) {
771 i++; /* skip two chars */
772 continue;
775 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
776 break;
778 i++; /* next hex digit */
780 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
781 break;
783 /* get the two nybbles */
784 hinybble = PTR_DIFF(p1, hexchars);
785 lonybble = PTR_DIFF(p2, hexchars);
787 p[num_chars] = (hinybble << 4) | lonybble;
788 num_chars++;
790 p1 = NULL;
791 p2 = NULL;
793 return num_chars;
797 * Routine to print a buffer as HEX digits, into an allocated string.
800 void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
802 int i;
803 char *hex_buffer;
805 *out_hex_buffer = smb_xmalloc((len*2)+1);
806 hex_buffer = *out_hex_buffer;
808 for (i = 0; i < len; i++)
809 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
813 Check if a string is part of a list.
816 BOOL in_list(char *s,char *list,BOOL casesensitive)
818 pstring tok;
819 const char *p=list;
821 if (!list)
822 return(False);
824 while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
825 if (casesensitive) {
826 if (strcmp(tok,s) == 0)
827 return(True);
828 } else {
829 if (StrCaseCmp(tok,s) == 0)
830 return(True);
833 return(False);
836 /* this is used to prevent lots of mallocs of size 1 */
837 static char *null_string = NULL;
840 Set a string value, allocing the space for the string
843 static BOOL string_init(char **dest,const char *src)
845 size_t l;
846 if (!src)
847 src = "";
849 l = strlen(src);
851 if (l == 0) {
852 if (!null_string) {
853 if((null_string = (char *)malloc(1)) == NULL) {
854 DEBUG(0,("string_init: malloc fail for null_string.\n"));
855 return False;
857 *null_string = 0;
859 *dest = null_string;
860 } else {
861 (*dest) = strdup(src);
862 if ((*dest) == NULL) {
863 DEBUG(0,("Out of memory in string_init\n"));
864 return False;
867 return(True);
871 Free a string value.
874 void string_free(char **s)
876 if (!s || !(*s))
877 return;
878 if (*s == null_string)
879 *s = NULL;
880 SAFE_FREE(*s);
884 Set a string value, deallocating any existing space, and allocing the space
885 for the string
888 BOOL string_set(char **dest,const char *src)
890 string_free(dest);
891 return(string_init(dest,src));
895 Substitute a string for a pattern in another string. Make sure there is
896 enough room!
898 This routine looks for pattern in s and replaces it with
899 insert. It may do multiple replacements.
901 Any of " ; ' $ or ` in the insert string are replaced with _
902 if len==0 then the string cannot be extended. This is different from the old
903 use of len==0 which was for no length checks to be done.
906 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
908 char *p;
909 ssize_t ls,lp,li, i;
911 if (!insert || !pattern || !*pattern || !s)
912 return;
914 ls = (ssize_t)strlen(s);
915 lp = (ssize_t)strlen(pattern);
916 li = (ssize_t)strlen(insert);
918 if (len == 0)
919 len = ls + 1; /* len is number of *bytes* */
921 while (lp <= ls && (p = strstr(s,pattern))) {
922 if (ls + (li-lp) >= len) {
923 DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n",
924 (int)(ls + (li-lp) - len),
925 pattern, (int)len));
926 break;
928 if (li != lp) {
929 memmove(p+li,p+lp,strlen(p+lp)+1);
931 for (i=0;i<li;i++) {
932 switch (insert[i]) {
933 case '`':
934 case '"':
935 case '\'':
936 case ';':
937 case '$':
938 case '%':
939 case '\r':
940 case '\n':
941 p[i] = '_';
942 break;
943 default:
944 p[i] = insert[i];
947 s = p + li;
948 ls += (li-lp);
952 void fstring_sub(char *s,const char *pattern,const char *insert)
954 string_sub(s, pattern, insert, sizeof(fstring));
957 void pstring_sub(char *s,const char *pattern,const char *insert)
959 string_sub(s, pattern, insert, sizeof(pstring));
963 Similar to string_sub, but it will accept only allocated strings
964 and may realloc them so pay attention at what you pass on no
965 pointers inside strings, no pstrings or const may be passed
966 as string.
969 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
971 char *p, *in;
972 char *s;
973 ssize_t ls,lp,li,ld, i;
975 if (!insert || !pattern || !*pattern || !string || !*string)
976 return NULL;
978 s = string;
980 in = strdup(insert);
981 if (!in) {
982 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
983 return NULL;
985 ls = (ssize_t)strlen(s);
986 lp = (ssize_t)strlen(pattern);
987 li = (ssize_t)strlen(insert);
988 ld = li - lp;
989 for (i=0;i<li;i++) {
990 switch (in[i]) {
991 case '`':
992 case '"':
993 case '\'':
994 case ';':
995 case '$':
996 case '%':
997 case '\r':
998 case '\n':
999 in[i] = '_';
1000 default:
1001 /* ok */
1002 break;
1006 while ((p = strstr(s,pattern))) {
1007 if (ld > 0) {
1008 int offset = PTR_DIFF(s,string);
1009 char *t = Realloc(string, ls + ld + 1);
1010 if (!t) {
1011 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1012 SAFE_FREE(in);
1013 return NULL;
1015 string = t;
1016 p = t + offset + (p - s);
1018 if (li != lp) {
1019 memmove(p+li,p+lp,strlen(p+lp)+1);
1021 memcpy(p, in, li);
1022 s = p + li;
1023 ls += ld;
1025 SAFE_FREE(in);
1026 return string;
1030 Similar to string_sub() but allows for any character to be substituted.
1031 Use with caution!
1032 if len==0 then the string cannot be extended. This is different from the old
1033 use of len==0 which was for no length checks to be done.
1036 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1038 char *p;
1039 ssize_t ls,lp,li;
1041 if (!insert || !pattern || !s)
1042 return;
1044 ls = (ssize_t)strlen(s);
1045 lp = (ssize_t)strlen(pattern);
1046 li = (ssize_t)strlen(insert);
1048 if (!*pattern)
1049 return;
1051 if (len == 0)
1052 len = ls + 1; /* len is number of *bytes* */
1054 while (lp <= ls && (p = strstr(s,pattern))) {
1055 if (ls + (li-lp) >= len) {
1056 DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n",
1057 (int)(ls + (li-lp) - len),
1058 pattern, (int)len));
1059 break;
1061 if (li != lp) {
1062 memmove(p+li,p+lp,strlen(p+lp)+1);
1064 memcpy(p, insert, li);
1065 s = p + li;
1066 ls += (li-lp);
1071 Similar to all_string_sub but for unicode strings.
1072 Return a new allocated unicode string.
1073 similar to string_sub() but allows for any character to be substituted.
1074 Use with caution!
1077 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
1078 const smb_ucs2_t *insert)
1080 smb_ucs2_t *r, *rp;
1081 const smb_ucs2_t *sp;
1082 size_t lr, lp, li, lt;
1084 if (!insert || !pattern || !*pattern || !s)
1085 return NULL;
1087 lt = (size_t)strlen_w(s);
1088 lp = (size_t)strlen_w(pattern);
1089 li = (size_t)strlen_w(insert);
1091 if (li > lp) {
1092 const smb_ucs2_t *st = s;
1093 int ld = li - lp;
1094 while ((sp = strstr_w(st, pattern))) {
1095 st = sp + lp;
1096 lt += ld;
1100 r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
1101 if (!r) {
1102 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
1103 return NULL;
1106 while ((sp = strstr_w(s, pattern))) {
1107 memcpy(rp, s, (sp - s));
1108 rp += ((sp - s) / sizeof(smb_ucs2_t));
1109 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
1110 s = sp + lp;
1111 rp += li;
1113 lr = ((rp - r) / sizeof(smb_ucs2_t));
1114 if (lr < lt) {
1115 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
1116 rp += (lt - lr);
1118 *rp = 0;
1120 return r;
1123 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
1124 const char *insert)
1126 wpstring p, i;
1128 if (!insert || !pattern || !s)
1129 return NULL;
1130 push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1131 push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1132 return all_string_sub_w(s, p, i);
1135 #if 0
1137 Splits out the front and back at a separator.
1140 static void split_at_last_component(char *path, char *front, char sep, char *back)
1142 char *p = strrchr_m(path, sep);
1144 if (p != NULL)
1145 *p = 0;
1147 if (front != NULL)
1148 pstrcpy(front, path);
1150 if (p != NULL) {
1151 if (back != NULL)
1152 pstrcpy(back, p+1);
1153 *p = '\\';
1154 } else {
1155 if (back != NULL)
1156 back[0] = 0;
1159 #endif
1162 Write an octal as a string.
1165 const char *octal_string(int i)
1167 static char ret[64];
1168 if (i == -1)
1169 return "-1";
1170 slprintf(ret, sizeof(ret)-1, "0%o", i);
1171 return ret;
1176 Truncate a string at a specified length.
1179 char *string_truncate(char *s, unsigned int length)
1181 if (s && strlen(s) > length)
1182 s[length] = 0;
1183 return s;
1187 Strchr and strrchr_m are very hard to do on general multi-byte strings.
1188 We convert via ucs2 for now.
1191 char *strchr_m(const char *src, char c)
1193 wpstring ws;
1194 pstring s2;
1195 smb_ucs2_t *p;
1196 const char *s;
1198 /* this is quite a common operation, so we want it to be
1199 fast. We optimise for the ascii case, knowing that all our
1200 supported multi-byte character sets are ascii-compatible
1201 (ie. they match for the first 128 chars) */
1203 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1204 if (*s == c)
1205 return (char *)s;
1208 if (!*s)
1209 return NULL;
1211 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1212 /* With compose characters we must restart from the beginning. JRA. */
1213 s = src;
1214 #endif
1216 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1217 p = strchr_w(ws, UCS2_CHAR(c));
1218 if (!p)
1219 return NULL;
1220 *p = 0;
1221 pull_ucs2_pstring(s2, ws);
1222 return (char *)(s+strlen(s2));
1225 char *strrchr_m(const char *s, char c)
1227 /* this is quite a common operation, so we want it to be
1228 fast. We optimise for the ascii case, knowing that all our
1229 supported multi-byte character sets are ascii-compatible
1230 (ie. they match for the first 128 chars). Also, in Samba
1231 we only search for ascii characters in 'c' and that
1232 in all mb character sets with a compound character
1233 containing c, if 'c' is not a match at position
1234 p, then p[-1] > 0x7f. JRA. */
1237 size_t len = strlen(s);
1238 const char *cp = s;
1239 BOOL got_mb = False;
1241 if (len == 0)
1242 return NULL;
1243 cp += (len - 1);
1244 do {
1245 if (c == *cp) {
1246 /* Could be a match. Part of a multibyte ? */
1247 if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
1248 /* Yep - go slow :-( */
1249 got_mb = True;
1250 break;
1252 /* No - we have a match ! */
1253 return (char *)cp;
1255 } while (cp-- != s);
1256 if (!got_mb)
1257 return NULL;
1260 /* String contained a non-ascii char. Slow path. */
1262 wpstring ws;
1263 pstring s2;
1264 smb_ucs2_t *p;
1266 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1267 p = strrchr_w(ws, UCS2_CHAR(c));
1268 if (!p)
1269 return NULL;
1270 *p = 0;
1271 pull_ucs2_pstring(s2, ws);
1272 return (char *)(s+strlen(s2));
1276 /***********************************************************************
1277 Return the equivalent of doing strrchr 'n' times - always going
1278 backwards.
1279 ***********************************************************************/
1281 char *strnrchr_m(const char *s, char c, unsigned int n)
1283 wpstring ws;
1284 pstring s2;
1285 smb_ucs2_t *p;
1287 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1288 p = strnrchr_w(ws, UCS2_CHAR(c), n);
1289 if (!p)
1290 return NULL;
1291 *p = 0;
1292 pull_ucs2_pstring(s2, ws);
1293 return (char *)(s+strlen(s2));
1297 Convert a string to lower case.
1300 void strlower_m(char *s)
1302 size_t len;
1304 /* this is quite a common operation, so we want it to be
1305 fast. We optimise for the ascii case, knowing that all our
1306 supported multi-byte character sets are ascii-compatible
1307 (ie. they match for the first 128 chars) */
1309 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1310 *s = tolower((unsigned char)*s);
1311 s++;
1314 if (!*s)
1315 return;
1317 /* I assume that lowercased string takes the same number of bytes
1318 * as source string even in UTF-8 encoding. (VIV) */
1319 len = strlen(s) + 1;
1320 errno = 0;
1321 unix_strlower(s,len,s,len);
1322 /* Catch mb conversion errors that may not terminate. */
1323 if (errno)
1324 s[len-1] = '\0';
1328 Convert a string to upper case.
1331 void strupper_m(char *s)
1333 size_t len;
1335 /* this is quite a common operation, so we want it to be
1336 fast. 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 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1341 *s = toupper((unsigned char)*s);
1342 s++;
1345 if (!*s)
1346 return;
1348 /* I assume that lowercased string takes the same number of bytes
1349 * as source string even in multibyte encoding. (VIV) */
1350 len = strlen(s) + 1;
1351 errno = 0;
1352 unix_strupper(s,len,s,len);
1353 /* Catch mb conversion errors that may not terminate. */
1354 if (errno)
1355 s[len-1] = '\0';
1359 Return a RFC2254 binary string representation of a buffer.
1360 Used in LDAP filters.
1361 Caller must free.
1364 char *binary_string(char *buf, int len)
1366 char *s;
1367 int i, j;
1368 const char *hex = "0123456789ABCDEF";
1369 s = malloc(len * 3 + 1);
1370 if (!s)
1371 return NULL;
1372 for (j=i=0;i<len;i++) {
1373 s[j] = '\\';
1374 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1375 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1376 j += 3;
1378 s[j] = 0;
1379 return s;
1383 Just a typesafety wrapper for snprintf into a pstring.
1386 int pstr_sprintf(pstring s, const char *fmt, ...)
1388 va_list ap;
1389 int ret;
1391 va_start(ap, fmt);
1392 ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1393 va_end(ap);
1394 return ret;
1399 Just a typesafety wrapper for snprintf into a fstring.
1402 int fstr_sprintf(fstring s, const char *fmt, ...)
1404 va_list ap;
1405 int ret;
1407 va_start(ap, fmt);
1408 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1409 va_end(ap);
1410 return ret;
1414 #ifndef HAVE_STRNDUP
1416 Some platforms don't have strndup.
1419 char *strndup(const char *s, size_t n)
1421 char *ret;
1423 n = strnlen(s, n);
1424 ret = malloc(n+1);
1425 if (!ret)
1426 return NULL;
1427 memcpy(ret, s, n);
1428 ret[n] = 0;
1430 return ret;
1432 #endif
1434 #ifndef HAVE_STRNLEN
1436 Some platforms don't have strnlen
1439 size_t strnlen(const char *s, size_t n)
1441 int i;
1442 for (i=0; s[i] && i<n; i++)
1443 /* noop */ ;
1444 return i;
1446 #endif
1449 List of Strings manipulation functions
1452 #define S_LIST_ABS 16 /* List Allocation Block Size */
1454 char **str_list_make(const char *string, const char *sep)
1456 char **list, **rlist;
1457 const char *str;
1458 char *s;
1459 int num, lsize;
1460 pstring tok;
1462 if (!string || !*string)
1463 return NULL;
1464 s = strdup(string);
1465 if (!s) {
1466 DEBUG(0,("str_list_make: Unable to allocate memory"));
1467 return NULL;
1469 if (!sep) sep = LIST_SEP;
1471 num = lsize = 0;
1472 list = NULL;
1474 str = s;
1475 while (next_token(&str, tok, sep, sizeof(tok))) {
1476 if (num == lsize) {
1477 lsize += S_LIST_ABS;
1478 rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1479 if (!rlist) {
1480 DEBUG(0,("str_list_make: Unable to allocate memory"));
1481 str_list_free(&list);
1482 SAFE_FREE(s);
1483 return NULL;
1484 } else
1485 list = rlist;
1486 memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1489 list[num] = strdup(tok);
1490 if (!list[num]) {
1491 DEBUG(0,("str_list_make: Unable to allocate memory"));
1492 str_list_free(&list);
1493 SAFE_FREE(s);
1494 return NULL;
1497 num++;
1500 SAFE_FREE(s);
1501 return list;
1504 BOOL str_list_copy(char ***dest, const char **src)
1506 char **list, **rlist;
1507 int num, lsize;
1509 *dest = NULL;
1510 if (!src)
1511 return False;
1513 num = lsize = 0;
1514 list = NULL;
1516 while (src[num]) {
1517 if (num == lsize) {
1518 lsize += S_LIST_ABS;
1519 rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1520 if (!rlist) {
1521 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1522 str_list_free(&list);
1523 return False;
1524 } else
1525 list = rlist;
1526 memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1529 list[num] = strdup(src[num]);
1530 if (!list[num]) {
1531 DEBUG(0,("str_list_copy: Unable to allocate memory"));
1532 str_list_free(&list);
1533 return False;
1536 num++;
1539 *dest = list;
1540 return True;
1544 * Return true if all the elements of the list match exactly.
1546 BOOL str_list_compare(char **list1, char **list2)
1548 int num;
1550 if (!list1 || !list2)
1551 return (list1 == list2);
1553 for (num = 0; list1[num]; num++) {
1554 if (!list2[num])
1555 return False;
1556 if (!strcsequal(list1[num], list2[num]))
1557 return False;
1559 if (list2[num])
1560 return False; /* if list2 has more elements than list1 fail */
1562 return True;
1565 void str_list_free(char ***list)
1567 char **tlist;
1569 if (!list || !*list)
1570 return;
1571 tlist = *list;
1572 for(; *tlist; tlist++)
1573 SAFE_FREE(*tlist);
1574 SAFE_FREE(*list);
1577 /******************************************************************************
1578 version of standard_sub_basic() for string lists; uses alloc_sub_basic()
1579 for the work
1580 *****************************************************************************/
1582 BOOL str_list_sub_basic( char **list, const char *smb_name )
1584 char *s, *tmpstr;
1586 while ( *list ) {
1587 s = *list;
1588 tmpstr = alloc_sub_basic(smb_name, s);
1589 if ( !tmpstr ) {
1590 DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
1591 return False;
1594 *list = tmpstr;
1596 list++;
1599 return True;
1602 /******************************************************************************
1603 substritute a specific pattern in a string list
1604 *****************************************************************************/
1606 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1608 char *p, *s, *t;
1609 ssize_t ls, lp, li, ld, i, d;
1611 if (!list)
1612 return False;
1613 if (!pattern)
1614 return False;
1615 if (!insert)
1616 return False;
1618 lp = (ssize_t)strlen(pattern);
1619 li = (ssize_t)strlen(insert);
1620 ld = li -lp;
1622 while (*list) {
1623 s = *list;
1624 ls = (ssize_t)strlen(s);
1626 while ((p = strstr(s, pattern))) {
1627 t = *list;
1628 d = p -t;
1629 if (ld) {
1630 t = (char *) malloc(ls +ld +1);
1631 if (!t) {
1632 DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1633 return False;
1635 memcpy(t, *list, d);
1636 memcpy(t +d +li, p +lp, ls -d -lp +1);
1637 SAFE_FREE(*list);
1638 *list = t;
1639 ls += ld;
1640 s = t +d +li;
1643 for (i = 0; i < li; i++) {
1644 switch (insert[i]) {
1645 case '`':
1646 case '"':
1647 case '\'':
1648 case ';':
1649 case '$':
1650 case '%':
1651 case '\r':
1652 case '\n':
1653 t[d +i] = '_';
1654 break;
1655 default:
1656 t[d +i] = insert[i];
1662 list++;
1665 return True;
1669 #define IPSTR_LIST_SEP ","
1670 #define IPSTR_LIST_CHAR ','
1673 * Add ip string representation to ipstr list. Used also
1674 * as part of @function ipstr_list_make
1676 * @param ipstr_list pointer to string containing ip list;
1677 * MUST BE already allocated and IS reallocated if necessary
1678 * @param ipstr_size pointer to current size of ipstr_list (might be changed
1679 * as a result of reallocation)
1680 * @param ip IP address which is to be added to list
1681 * @return pointer to string appended with new ip and possibly
1682 * reallocated to new length
1685 char* ipstr_list_add(char** ipstr_list, const struct ip_service *service)
1687 char* new_ipstr = NULL;
1689 /* arguments checking */
1690 if (!ipstr_list || !service) return NULL;
1692 /* attempt to convert ip to a string and append colon separator to it */
1693 if (*ipstr_list) {
1694 asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP,
1695 inet_ntoa(service->ip), service->port);
1696 SAFE_FREE(*ipstr_list);
1697 } else {
1698 asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port);
1700 *ipstr_list = new_ipstr;
1701 return *ipstr_list;
1706 * Allocate and initialise an ipstr list using ip adresses
1707 * passed as arguments.
1709 * @param ipstr_list pointer to string meant to be allocated and set
1710 * @param ip_list array of ip addresses to place in the list
1711 * @param ip_count number of addresses stored in ip_list
1712 * @return pointer to allocated ip string
1715 char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count)
1717 int i;
1719 /* arguments checking */
1720 if (!ip_list && !ipstr_list) return 0;
1722 *ipstr_list = NULL;
1724 /* process ip addresses given as arguments */
1725 for (i = 0; i < ip_count; i++)
1726 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1728 return (*ipstr_list);
1733 * Parse given ip string list into array of ip addresses
1734 * (as ip_service structures)
1735 * e.g. 192.168.1.100:389,192.168.1.78, ...
1737 * @param ipstr ip string list to be parsed
1738 * @param ip_list pointer to array of ip addresses which is
1739 * allocated by this function and must be freed by caller
1740 * @return number of succesfully parsed addresses
1743 int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list)
1745 fstring token_str;
1746 size_t count;
1747 int i;
1749 if (!ipstr_list || !ip_list)
1750 return 0;
1752 count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1753 if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) {
1754 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count));
1755 return 0;
1758 for ( i=0;
1759 next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count;
1760 i++ )
1762 struct in_addr addr;
1763 unsigned port = 0;
1764 char *p = strchr(token_str, ':');
1766 if (p) {
1767 *p = 0;
1768 port = atoi(p+1);
1771 /* convert single token to ip address */
1772 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1773 break;
1775 (*ip_list)[i].ip = addr;
1776 (*ip_list)[i].port = port;
1779 return count;
1784 * Safely free ip string list
1786 * @param ipstr_list ip string list to be freed
1789 void ipstr_list_free(char* ipstr_list)
1791 SAFE_FREE(ipstr_list);
1796 Unescape a URL encoded string, in place.
1799 void rfc1738_unescape(char *buf)
1801 char *p=buf;
1803 while (p && *p && (p=strchr_m(p,'%'))) {
1804 int c1 = p[1];
1805 int c2 = p[2];
1807 if (c1 >= '0' && c1 <= '9')
1808 c1 = c1 - '0';
1809 else if (c1 >= 'A' && c1 <= 'F')
1810 c1 = 10 + c1 - 'A';
1811 else if (c1 >= 'a' && c1 <= 'f')
1812 c1 = 10 + c1 - 'a';
1813 else {p++; continue;}
1815 if (c2 >= '0' && c2 <= '9')
1816 c2 = c2 - '0';
1817 else if (c2 >= 'A' && c2 <= 'F')
1818 c2 = 10 + c2 - 'A';
1819 else if (c2 >= 'a' && c2 <= 'f')
1820 c2 = 10 + c2 - 'a';
1821 else {p++; continue;}
1823 *p = (c1<<4) | c2;
1825 memmove(p+1, p+3, strlen(p+3)+1);
1826 p++;
1830 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1833 * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
1835 DATA_BLOB base64_decode_data_blob(const char *s)
1837 int bit_offset, byte_offset, idx, i, n;
1838 DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1839 unsigned char *d = decoded.data;
1840 char *p;
1842 n=i=0;
1844 while (*s && (p=strchr_m(b64,*s))) {
1845 idx = (int)(p - b64);
1846 byte_offset = (i*6)/8;
1847 bit_offset = (i*6)%8;
1848 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1849 if (bit_offset < 3) {
1850 d[byte_offset] |= (idx << (2-bit_offset));
1851 n = byte_offset+1;
1852 } else {
1853 d[byte_offset] |= (idx >> (bit_offset-2));
1854 d[byte_offset+1] = 0;
1855 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1856 n = byte_offset+2;
1858 s++; i++;
1861 if (*s == '=') n -= 1;
1863 /* fix up length */
1864 decoded.length = n;
1865 return decoded;
1869 * Decode a base64 string in-place - wrapper for the above
1871 void base64_decode_inplace(char *s)
1873 DATA_BLOB decoded = base64_decode_data_blob(s);
1874 memcpy(s, decoded.data, decoded.length);
1875 /* null terminate */
1876 s[decoded.length] = '\0';
1878 data_blob_free(&decoded);
1882 * Encode a base64 string into a malloc()ed string caller to free.
1884 *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
1886 char * base64_encode_data_blob(DATA_BLOB data)
1888 int bits = 0;
1889 int char_count = 0;
1890 size_t out_cnt = 0;
1891 size_t len = data.length;
1892 size_t output_len = data.length * 2;
1893 char *result = malloc(output_len); /* get us plenty of space */
1895 while (len-- && out_cnt < (data.length * 2) - 5) {
1896 int c = (unsigned char) *(data.data++);
1897 bits += c;
1898 char_count++;
1899 if (char_count == 3) {
1900 result[out_cnt++] = b64[bits >> 18];
1901 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1902 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1903 result[out_cnt++] = b64[bits & 0x3f];
1904 bits = 0;
1905 char_count = 0;
1906 } else {
1907 bits <<= 8;
1910 if (char_count != 0) {
1911 bits <<= 16 - (8 * char_count);
1912 result[out_cnt++] = b64[bits >> 18];
1913 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1914 if (char_count == 1) {
1915 result[out_cnt++] = '=';
1916 result[out_cnt++] = '=';
1917 } else {
1918 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1919 result[out_cnt++] = '=';
1922 result[out_cnt] = '\0'; /* terminate */
1923 return result;
1926 /* read a SMB_BIG_UINT from a string */
1927 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1930 SMB_BIG_UINT val = -1;
1931 const char *p = nptr;
1933 while (p && *p && isspace(*p))
1934 p++;
1935 #ifdef LARGE_SMB_OFF_T
1936 sscanf(p,"%llu",&val);
1937 #else /* LARGE_SMB_OFF_T */
1938 sscanf(p,"%lu",&val);
1939 #endif /* LARGE_SMB_OFF_T */
1940 if (entptr) {
1941 while (p && *p && isdigit(*p))
1942 p++;
1943 *entptr = p;
1946 return val;