This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[ira/wip.git] / source3 / lib / util_str.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    
5    Copyright (C) Andrew Tridgell 1992-2001
6    Copyright (C) Simo Sorce      2001-2002
7    Copyright (C) Martin Pool     2003
8    
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.
13    
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.
18    
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.
22 */
23
24 #include "includes.h"
25
26 /**
27  * @file
28  * @brief String utilities.
29  **/
30
31 /**
32  * Get the next token from a string, return False if none found.
33  * Handles double-quotes.
34  * 
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)
39 {
40         const char *s;
41         BOOL quoted;
42         size_t len=1;
43
44         if (!ptr)
45                 return(False);
46
47         s = *ptr;
48
49         /* default to simple separators */
50         if (!sep)
51                 sep = " \t\n\r";
52
53         /* find the first non sep char */
54         while (*s && strchr_m(sep,*s))
55                 s++;
56         
57         /* nothing left? */
58         if (! *s)
59                 return(False);
60         
61         /* copy over the token */
62         for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
63                 if (*s == '\"') {
64                         quoted = !quoted;
65                 } else {
66                         len++;
67                         *buff++ = *s;
68                 }
69         }
70         
71         *ptr = (*s) ? s+1 : s;  
72         *buff = 0;
73         
74         return(True);
75 }
76
77 /**
78 This is like next_token but is not re-entrant and "remembers" the first 
79 parameter so you can pass NULL. This is useful for user interface code
80 but beware the fact that it is not re-entrant!
81 **/
82
83 static const char *last_ptr=NULL;
84
85 BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
86 {
87         BOOL ret;
88         if (!ptr)
89                 ptr = (const char **)&last_ptr;
90
91         ret = next_token(ptr, buff, sep, bufsize);
92         last_ptr = *ptr;
93         return ret;     
94 }
95
96 static uint16 tmpbuf[sizeof(pstring)];
97
98 void set_first_token(char *ptr)
99 {
100         last_ptr = ptr;
101 }
102
103 /**
104  Convert list of tokens to array; dependent on above routine.
105  Uses last_ptr from above - bit of a hack.
106 **/
107
108 char **toktocliplist(int *ctok, const char *sep)
109 {
110         char *s=last_ptr;
111         int ictok=0;
112         char **ret, **iret;
113
114         if (!sep)
115                 sep = " \t\n\r";
116
117         while(*s && strchr_m(sep,*s))
118                 s++;
119
120         /* nothing left? */
121         if (!*s)
122                 return(NULL);
123
124         do {
125                 ictok++;
126                 while(*s && (!strchr_m(sep,*s)))
127                         s++;
128                 while(*s && strchr_m(sep,*s))
129                         *s++=0;
130         } while(*s);
131         
132         *ctok=ictok;
133         s=last_ptr;
134         
135         if (!(ret=iret=malloc(ictok*sizeof(char *))))
136                 return NULL;
137         
138         while(ictok--) {    
139                 *iret++=s;
140                 while(*s++)
141                         ;
142                 while(!*s)
143                         s++;
144         }
145
146         return ret;
147 }
148
149 /**
150  * Case insensitive string compararison.
151  *
152  * iconv does not directly give us a way to compare strings in
153  * arbitrary unix character sets -- all we can is convert and then
154  * compare.  This is expensive.
155  *
156  * As an optimization, we do a first pass that considers only the
157  * prefix of the strings that is entirely 7-bit.  Within this, we
158  * check whether they have the same value.
159  *
160  * Hopefully this will often give the answer without needing to copy.
161  * In particular it should speed comparisons to literal ascii strings
162  * or comparisons of strings that are "obviously" different.
163  *
164  * If we find a non-ascii character we fall back to converting via
165  * iconv.
166  *
167  * This should never be slower than convering the whole thing, and
168  * often faster.
169  *
170  * A different optimization would be to compare for bitwise equality
171  * in the binary encoding.  (It would be possible thought hairy to do
172  * both simultaneously.)  But in that case if they turn out to be
173  * different, we'd need to restart the whole thing.
174  *
175  * Even better is to implement strcasecmp for each encoding and use a
176  * function pointer. 
177  **/
178 int StrCaseCmp(const char *s, const char *t)
179 {
180
181         const char * ps, * pt;
182         pstring buf1, buf2;
183
184         for (ps = s, pt = t; ; ps++, pt++) {
185                 char us, ut;
186
187                 if (!*ps && !*pt)
188                         return 0; /* both ended */
189                 else if (!*ps)
190                         return -1; /* s is a prefix */
191                 else if (!*pt)
192                         return +1; /* t is a prefix */
193                 else if ((*ps & 0x80) || (*pt & 0x80))
194                         /* not ascii anymore, do it the hard way from here on in */
195                         break;
196
197                 us = toupper(*ps);
198                 ut = toupper(*pt);
199                 if (us == ut)
200                         continue;
201                 else if (us < ut)
202                         return -1;
203                 else if (us > ut)
204                         return +1;
205         }
206
207         /* TODO: Don't do this with a fixed-length buffer.  This could
208          * still be much more efficient. */
209         /* TODO: Hardcode a char-by-char comparison for UTF-8, which
210          * can be much faster. */
211         /* TODO: Test case for this! */
212
213         unix_strupper(ps, strlen(ps)+1, buf1, sizeof(buf1));
214         unix_strupper(pt, strlen(pt)+1, buf2, sizeof(buf2));
215
216         return strcmp(buf1, buf2);
217 }
218
219
220 /**
221  Case insensitive string compararison, length limited.
222 **/
223 int StrnCaseCmp(const char *s, const char *t, size_t n)
224 {
225         pstring buf1, buf2;
226         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
227         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
228         return strncmp(buf1,buf2,n);
229 }
230
231 /**
232  * Compare 2 strings.
233  *
234  * @note The comparison is case-insensitive.
235  **/
236 BOOL strequal(const char *s1, const char *s2)
237 {
238         if (s1 == s2)
239                 return(True);
240         if (!s1 || !s2)
241                 return(False);
242   
243         return(StrCaseCmp(s1,s2)==0);
244 }
245
246 /**
247  * Compare 2 strings up to and including the nth char.
248  *
249  * @note The comparison is case-insensitive.
250  **/
251 BOOL strnequal(const char *s1,const char *s2,size_t n)
252 {
253   if (s1 == s2)
254           return(True);
255   if (!s1 || !s2 || !n)
256           return(False);
257   
258   return(StrnCaseCmp(s1,s2,n)==0);
259 }
260
261 /**
262  Compare 2 strings (case sensitive).
263 **/
264
265 BOOL strcsequal(const char *s1,const char *s2)
266 {
267   if (s1 == s2)
268           return(True);
269   if (!s1 || !s2)
270           return(False);
271   
272   return(strcmp(s1,s2)==0);
273 }
274
275 /**
276 Do a case-insensitive, whitespace-ignoring string compare.
277 **/
278
279 int strwicmp(const char *psz1, const char *psz2)
280 {
281         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
282         /* appropriate value. */
283         if (psz1 == psz2)
284                 return (0);
285         else if (psz1 == NULL)
286                 return (-1);
287         else if (psz2 == NULL)
288                 return (1);
289
290         /* sync the strings on first non-whitespace */
291         while (1) {
292                 while (isspace((int)*psz1))
293                         psz1++;
294                 while (isspace((int)*psz2))
295                         psz2++;
296                 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
297                     || *psz2 == '\0')
298                         break;
299                 psz1++;
300                 psz2++;
301         }
302         return (*psz1 - *psz2);
303 }
304
305
306 /**
307  Convert a string to upper case, but don't modify it.
308 **/
309
310 char *strupper_static(const char *s)
311 {
312         static pstring str;
313
314         pstrcpy(str, s);
315         strupper(str);
316
317         return str;
318 }
319
320 /**
321  Convert a string to "normal" form.
322 **/
323
324 void strnorm(char *s)
325 {
326         extern int case_default;
327         if (case_default == CASE_UPPER)
328                 strupper(s);
329         else
330                 strlower(s);
331 }
332
333 /**
334  Check if a string is in "normal" case.
335 **/
336
337 BOOL strisnormal(const char *s)
338 {
339         extern int case_default;
340         if (case_default == CASE_UPPER)
341                 return(!strhaslower(s));
342         
343         return(!strhasupper(s));
344 }
345
346
347 /**
348  String replace.
349  NOTE: oldc and newc must be 7 bit characters
350 **/
351
352 void string_replace(char *s,char oldc,char newc)
353 {
354         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
355         string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
356         pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
357 }
358
359 /**
360  Skip past some strings in a buffer.
361 **/
362
363 char *skip_string(char *buf,size_t n)
364 {
365         while (n--)
366                 buf += strlen(buf) + 1;
367         return(buf);
368 }
369
370 /**
371  Count the number of characters in a string. Normally this will
372  be the same as the number of bytes in a string for single byte strings,
373  but will be different for multibyte.
374 **/
375
376 size_t str_charnum(const char *s)
377 {
378         uint16 tmpbuf2[sizeof(pstring)];
379         push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
380         return strlen_w(tmpbuf2);
381 }
382
383 /**
384  Count the number of characters in a string. Normally this will
385  be the same as the number of bytes in a string for single byte strings,
386  but will be different for multibyte.
387 **/
388
389 size_t str_ascii_charnum(const char *s)
390 {
391         pstring tmpbuf2;
392         push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
393         return strlen(tmpbuf2);
394 }
395
396 /**
397  Trim the specified elements off the front and back of a string.
398 **/
399
400 BOOL trim_string(char *s,const char *front,const char *back)
401 {
402         BOOL ret = False;
403         size_t front_len;
404         size_t back_len;
405         size_t len;
406
407         /* Ignore null or empty strings. */
408         if (!s || (s[0] == '\0'))
409                 return False;
410
411         front_len       = front? strlen(front) : 0;
412         back_len        = back? strlen(back) : 0;
413
414         len = strlen(s);
415
416         if (front_len) {
417                 while (len && strncmp(s, front, front_len)==0) {
418                         memcpy(s, s+front_len, (len-front_len)+1);
419                         len -= front_len;
420                         ret=True;
421                 }
422         }
423         
424         if (back_len) {
425                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
426                         s[len-back_len]='\0';
427                         len -= back_len;
428                         ret=True;
429                 }
430         }
431         return ret;
432 }
433
434 /**
435  Does a string have any uppercase chars in it?
436 **/
437
438 BOOL strhasupper(const char *s)
439 {
440         smb_ucs2_t *ptr;
441         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
442         for(ptr=tmpbuf;*ptr;ptr++)
443                 if(isupper_w(*ptr))
444                         return True;
445         return(False);
446 }
447
448 /**
449  Does a string have any lowercase chars in it?
450 **/
451
452 BOOL strhaslower(const char *s)
453 {
454         smb_ucs2_t *ptr;
455         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
456         for(ptr=tmpbuf;*ptr;ptr++)
457                 if(islower_w(*ptr))
458                         return True;
459         return(False);
460 }
461
462 /**
463  Find the number of 'c' chars in a string
464 **/
465
466 size_t count_chars(const char *s,char c)
467 {
468         smb_ucs2_t *ptr;
469         int count;
470         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
471         for(count=0,ptr=tmpbuf;*ptr;ptr++)
472                 if(*ptr==UCS2_CHAR(c))
473                         count++;
474         return(count);
475 }
476
477 /**
478  Safe string copy into a known length string. maxlength does not
479  include the terminating zero.
480 **/
481
482 char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_t maxlength)
483 {
484         size_t len;
485
486         if (!dest) {
487                 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
488                 return NULL;
489         }
490
491         clobber_region(fn,line,dest, maxlength+1);
492
493         if (!src) {
494                 *dest = 0;
495                 return dest;
496         }  
497
498         len = strnlen(src, maxlength+1);
499
500         if (len > maxlength) {
501                 DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
502                          (unsigned int)(len-maxlength), len, maxlength, src));
503                 len = maxlength;
504         }
505       
506         memmove(dest, src, len);
507         dest[len] = 0;
508         return dest;
509 }  
510
511 /**
512  Safe string cat into a string. maxlength does not
513  include the terminating zero.
514 **/
515 char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
516 {
517         size_t src_len, dest_len;
518
519         if (!dest) {
520                 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
521                 return NULL;
522         }
523
524         if (!src)
525                 return dest;
526         
527         src_len = strnlen(src, maxlength + 1);
528         dest_len = strnlen(dest, maxlength + 1);
529
530         clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
531
532         if (src_len + dest_len > maxlength) {
533                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
534                          (int)(src_len + dest_len - maxlength), src));
535                 if (maxlength > dest_len) {
536                         memcpy(&dest[dest_len], src, maxlength - dest_len);
537                 }
538                 dest[maxlength] = 0;
539                 return NULL;
540         }
541
542         memcpy(&dest[dest_len], src, src_len);
543         dest[dest_len + src_len] = 0;
544         return dest;
545 }
546
547 /**
548  Paranoid strcpy into a buffer of given length (includes terminating
549  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
550  and replaces with '_'. Deliberately does *NOT* check for multibyte
551  characters. Don't change it !
552 **/
553 char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
554 {
555         size_t len, i;
556
557         clobber_region(fn, line, dest, maxlength);
558
559         if (!dest) {
560                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
561                 return NULL;
562         }
563
564         if (!src) {
565                 *dest = 0;
566                 return dest;
567         }  
568
569         len = strlen(src);
570         if (len >= maxlength)
571                 len = maxlength - 1;
572
573         if (!other_safe_chars)
574                 other_safe_chars = "";
575
576         for(i = 0; i < len; i++) {
577                 int val = (src[i] & 0xff);
578                 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
579                         dest[i] = src[i];
580                 else
581                         dest[i] = '_';
582         }
583
584         dest[i] = '\0';
585
586         return dest;
587 }
588
589 /**
590  Like strncpy but always null terminates. Make sure there is room!
591  The variable n should always be one less than the available size.
592 **/
593 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
594 {
595         char *d = dest;
596
597         clobber_region(fn, line, dest, n+1);
598
599         if (!dest)
600                 return(NULL);
601         
602         if (!src) {
603                 *dest = 0;
604                 return(dest);
605         }
606         
607         while (n-- && (*d = *src)) {
608                 d++;
609                 src++;
610         }
611
612         *d = 0;
613         return(dest);
614 }
615
616 #if 0
617 /**
618  Like strncpy but copies up to the character marker.  always null terminates.
619  returns a pointer to the character marker in the source string (src).
620 **/
621
622 static char *strncpyn(char *dest, const char *src, size_t n, char c)
623 {
624         char *p;
625         size_t str_len;
626
627         clobber_region(dest, n+1);
628
629         p = strchr_m(src, c);
630         if (p == NULL) {
631                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
632                 return NULL;
633         }
634
635         str_len = PTR_DIFF(p, src);
636         strncpy(dest, src, MIN(n, str_len));
637         dest[str_len] = '\0';
638
639         return p;
640 }
641 #endif
642
643 /**
644  Routine to get hex characters and turn them into a 16 byte array.
645  the array can be variable length, and any non-hex-numeric
646  characters are skipped.  "0xnn" or "0Xnn" is specially catered
647  for.
648
649  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
650
651 **/
652
653 size_t strhex_to_str(char *p, size_t len, const char *strhex)
654 {
655         size_t i;
656         size_t num_chars = 0;
657         unsigned char   lonybble, hinybble;
658         const char     *hexchars = "0123456789ABCDEF";
659         char           *p1 = NULL, *p2 = NULL;
660
661         for (i = 0; i < len && strhex[i] != 0; i++) {
662                 if (strnequal(hexchars, "0x", 2)) {
663                         i++; /* skip two chars */
664                         continue;
665                 }
666
667                 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
668                         break;
669
670                 i++; /* next hex digit */
671
672                 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
673                         break;
674
675                 /* get the two nybbles */
676                 hinybble = PTR_DIFF(p1, hexchars);
677                 lonybble = PTR_DIFF(p2, hexchars);
678
679                 p[num_chars] = (hinybble << 4) | lonybble;
680                 num_chars++;
681
682                 p1 = NULL;
683                 p2 = NULL;
684         }
685         return num_chars;
686 }
687
688 /**
689  * Routine to print a buffer as HEX digits, into an allocated string.
690  */
691
692 void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
693 {
694         int i;
695         char *hex_buffer;
696
697         *out_hex_buffer = smb_xmalloc((len*2)+1);
698         hex_buffer = *out_hex_buffer;
699
700         for (i = 0; i < len; i++)
701                 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
702 }
703
704 /**
705  Check if a string is part of a list.
706 **/
707
708 BOOL in_list(char *s,char *list,BOOL casesensitive)
709 {
710         pstring tok;
711         const char *p=list;
712
713         if (!list)
714                 return(False);
715
716         while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
717                 if (casesensitive) {
718                         if (strcmp(tok,s) == 0)
719                                 return(True);
720                 } else {
721                         if (StrCaseCmp(tok,s) == 0)
722                                 return(True);
723                 }
724         }
725         return(False);
726 }
727
728 /* this is used to prevent lots of mallocs of size 1 */
729 static char *null_string = NULL;
730
731 /**
732  Set a string value, allocing the space for the string
733 **/
734
735 static BOOL string_init(char **dest,const char *src)
736 {
737         size_t l;
738         if (!src)     
739                 src = "";
740
741         l = strlen(src);
742
743         if (l == 0) {
744                 if (!null_string) {
745                         if((null_string = (char *)malloc(1)) == NULL) {
746                                 DEBUG(0,("string_init: malloc fail for null_string.\n"));
747                                 return False;
748                         }
749                         *null_string = 0;
750                 }
751                 *dest = null_string;
752         } else {
753                 (*dest) = strdup(src);
754                 if ((*dest) == NULL) {
755                         DEBUG(0,("Out of memory in string_init\n"));
756                         return False;
757                 }
758         }
759         return(True);
760 }
761
762 /**
763  Free a string value.
764 **/
765
766 void string_free(char **s)
767 {
768         if (!s || !(*s))
769                 return;
770         if (*s == null_string)
771                 *s = NULL;
772         SAFE_FREE(*s);
773 }
774
775 /**
776  Set a string value, deallocating any existing space, and allocing the space
777  for the string
778 **/
779
780 BOOL string_set(char **dest,const char *src)
781 {
782         string_free(dest);
783         return(string_init(dest,src));
784 }
785
786 /**
787  Substitute a string for a pattern in another string. Make sure there is 
788  enough room!
789
790  This routine looks for pattern in s and replaces it with 
791  insert. It may do multiple replacements.
792
793  Any of " ; ' $ or ` in the insert string are replaced with _
794  if len==0 then the string cannot be extended. This is different from the old
795  use of len==0 which was for no length checks to be done.
796 **/
797
798 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
799 {
800         char *p;
801         ssize_t ls,lp,li, i;
802
803         if (!insert || !pattern || !*pattern || !s)
804                 return;
805
806         ls = (ssize_t)strlen(s);
807         lp = (ssize_t)strlen(pattern);
808         li = (ssize_t)strlen(insert);
809
810         if (len == 0)
811                 len = ls + 1; /* len is number of *bytes* */
812
813         while (lp <= ls && (p = strstr(s,pattern))) {
814                 if (ls + (li-lp) >= len) {
815                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
816                                  (int)(ls + (li-lp) - len),
817                                  pattern, (int)len));
818                         break;
819                 }
820                 if (li != lp) {
821                         memmove(p+li,p+lp,strlen(p+lp)+1);
822                 }
823                 for (i=0;i<li;i++) {
824                         switch (insert[i]) {
825                         case '`':
826                         case '"':
827                         case '\'':
828                         case ';':
829                         case '$':
830                         case '%':
831                         case '\r':
832                         case '\n':
833                                 p[i] = '_';
834                                 break;
835                         default:
836                                 p[i] = insert[i];
837                         }
838                 }
839                 s = p + li;
840                 ls += (li-lp);
841         }
842 }
843
844 void fstring_sub(char *s,const char *pattern,const char *insert)
845 {
846         string_sub(s, pattern, insert, sizeof(fstring));
847 }
848
849 void pstring_sub(char *s,const char *pattern,const char *insert)
850 {
851         string_sub(s, pattern, insert, sizeof(pstring));
852 }
853
854 /**
855  Similar to string_sub, but it will accept only allocated strings
856  and may realloc them so pay attention at what you pass on no
857  pointers inside strings, no pstrings or const may be passed
858  as string.
859 **/
860
861 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
862 {
863         char *p, *in;
864         char *s;
865         ssize_t ls,lp,li,ld, i;
866
867         if (!insert || !pattern || !*pattern || !string || !*string)
868                 return NULL;
869
870         s = string;
871
872         in = strdup(insert);
873         if (!in) {
874                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
875                 return NULL;
876         }
877         ls = (ssize_t)strlen(s);
878         lp = (ssize_t)strlen(pattern);
879         li = (ssize_t)strlen(insert);
880         ld = li - lp;
881         for (i=0;i<li;i++) {
882                 switch (in[i]) {
883                         case '`':
884                         case '"':
885                         case '\'':
886                         case ';':
887                         case '$':
888                         case '%':
889                         case '\r':
890                         case '\n':
891                                 in[i] = '_';
892                         default:
893                                 /* ok */
894                                 break;
895                 }
896         }
897         
898         while ((p = strstr(s,pattern))) {
899                 if (ld > 0) {
900                         char *t = Realloc(string, ls + ld + 1);
901                         if (!t) {
902                                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
903                                 SAFE_FREE(in);
904                                 return NULL;
905                         }
906                         string = t;
907                         p = t + (p - s);
908                 }
909                 if (li != lp) {
910                         memmove(p+li,p+lp,strlen(p+lp)+1);
911                 }
912                 memcpy(p, in, li);
913                 s = p + li;
914                 ls += ld;
915         }
916         SAFE_FREE(in);
917         return string;
918 }
919
920 /**
921  Similar to string_sub() but allows for any character to be substituted. 
922  Use with caution!
923  if len==0 then the string cannot be extended. This is different from the old
924  use of len==0 which was for no length checks to be done.
925 **/
926
927 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
928 {
929         char *p;
930         ssize_t ls,lp,li;
931
932         if (!insert || !pattern || !s)
933                 return;
934
935         ls = (ssize_t)strlen(s);
936         lp = (ssize_t)strlen(pattern);
937         li = (ssize_t)strlen(insert);
938
939         if (!*pattern)
940                 return;
941         
942         if (len == 0)
943                 len = ls + 1; /* len is number of *bytes* */
944         
945         while (lp <= ls && (p = strstr(s,pattern))) {
946                 if (ls + (li-lp) >= len) {
947                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
948                                  (int)(ls + (li-lp) - len),
949                                  pattern, (int)len));
950                         break;
951                 }
952                 if (li != lp) {
953                         memmove(p+li,p+lp,strlen(p+lp)+1);
954                 }
955                 memcpy(p, insert, li);
956                 s = p + li;
957                 ls += (li-lp);
958         }
959 }
960
961 /**
962  Similar to all_string_sub but for unicode strings.
963  Return a new allocated unicode string.
964  similar to string_sub() but allows for any character to be substituted.
965  Use with caution!
966 **/
967
968 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
969                                 const smb_ucs2_t *insert)
970 {
971         smb_ucs2_t *r, *rp;
972         const smb_ucs2_t *sp;
973         size_t  lr, lp, li, lt;
974
975         if (!insert || !pattern || !*pattern || !s)
976                 return NULL;
977
978         lt = (size_t)strlen_w(s);
979         lp = (size_t)strlen_w(pattern);
980         li = (size_t)strlen_w(insert);
981
982         if (li > lp) {
983                 const smb_ucs2_t *st = s;
984                 int ld = li - lp;
985                 while ((sp = strstr_w(st, pattern))) {
986                         st = sp + lp;
987                         lt += ld;
988                 }
989         }
990
991         r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
992         if (!r) {
993                 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
994                 return NULL;
995         }
996
997         while ((sp = strstr_w(s, pattern))) {
998                 memcpy(rp, s, (sp - s));
999                 rp += ((sp - s) / sizeof(smb_ucs2_t));
1000                 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
1001                 s = sp + lp;
1002                 rp += li;
1003         }
1004         lr = ((rp - r) / sizeof(smb_ucs2_t));
1005         if (lr < lt) {
1006                 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
1007                 rp += (lt - lr);
1008         }
1009         *rp = 0;
1010
1011         return r;
1012 }
1013
1014 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
1015                                              const char *insert)
1016 {
1017         wpstring p, i;
1018
1019         if (!insert || !pattern || !s)
1020                 return NULL;
1021         push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1022         push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1023         return all_string_sub_w(s, p, i);
1024 }
1025
1026 #if 0
1027 /**
1028  Splits out the front and back at a separator.
1029 **/
1030
1031 static void split_at_last_component(char *path, char *front, char sep, char *back)
1032 {
1033         char *p = strrchr_m(path, sep);
1034
1035         if (p != NULL)
1036                 *p = 0;
1037
1038         if (front != NULL)
1039                 pstrcpy(front, path);
1040
1041         if (p != NULL) {
1042                 if (back != NULL)
1043                         pstrcpy(back, p+1);
1044                 *p = '\\';
1045         } else {
1046                 if (back != NULL)
1047                         back[0] = 0;
1048         }
1049 }
1050 #endif
1051
1052 /**
1053  Write an octal as a string.
1054 **/
1055
1056 const char *octal_string(int i)
1057 {
1058         static char ret[64];
1059         if (i == -1)
1060                 return "-1";
1061         slprintf(ret, sizeof(ret)-1, "0%o", i);
1062         return ret;
1063 }
1064
1065
1066 /**
1067  Truncate a string at a specified length.
1068 **/
1069
1070 char *string_truncate(char *s, unsigned int length)
1071 {
1072         if (s && strlen(s) > length)
1073                 s[length] = 0;
1074         return s;
1075 }
1076
1077 /**
1078  Strchr and strrchr_m are very hard to do on general multi-byte strings. 
1079  We convert via ucs2 for now.
1080 **/
1081
1082 char *strchr_m(const char *s, char c)
1083 {
1084         wpstring ws;
1085         pstring s2;
1086         smb_ucs2_t *p;
1087
1088         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1089         p = strchr_w(ws, UCS2_CHAR(c));
1090         if (!p)
1091                 return NULL;
1092         *p = 0;
1093         pull_ucs2_pstring(s2, ws);
1094         return (char *)(s+strlen(s2));
1095 }
1096
1097 char *strrchr_m(const char *s, char c)
1098 {
1099         wpstring ws;
1100         pstring s2;
1101         smb_ucs2_t *p;
1102
1103         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1104         p = strrchr_w(ws, UCS2_CHAR(c));
1105         if (!p)
1106                 return NULL;
1107         *p = 0;
1108         pull_ucs2_pstring(s2, ws);
1109         return (char *)(s+strlen(s2));
1110 }
1111
1112 /**
1113  Convert a string to lower case.
1114 **/
1115
1116 void strlower_m(char *s)
1117 {
1118         /* this is quite a common operation, so we want it to be
1119            fast. We optimise for the ascii case, knowing that all our
1120            supported multi-byte character sets are ascii-compatible
1121            (ie. they match for the first 128 chars) */
1122
1123         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1124                 *s = tolower((unsigned char)*s);
1125                 s++;
1126         }
1127
1128         if (!*s)
1129                 return;
1130
1131         /* I assume that lowercased string takes the same number of bytes
1132          * as source string even in UTF-8 encoding. (VIV) */
1133         unix_strlower(s,strlen(s)+1,s,strlen(s)+1);     
1134 }
1135
1136 /**
1137  Duplicate convert a string to lower case.
1138 **/
1139
1140 char *strdup_lower(const char *s)
1141 {
1142         char *t = strdup(s);
1143         if (t == NULL) {
1144                 DEBUG(0, ("strdup_lower: Out of memory!\n"));
1145                 return NULL;
1146         }
1147         strlower_m(t);
1148         return t;
1149 }
1150
1151 /**
1152  Convert a string to upper case.
1153 **/
1154
1155 void strupper_m(char *s)
1156 {
1157         /* this is quite a common operation, so we want it to be
1158            fast. We optimise for the ascii case, knowing that all our
1159            supported multi-byte character sets are ascii-compatible
1160            (ie. they match for the first 128 chars) */
1161
1162         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1163                 *s = toupper((unsigned char)*s);
1164                 s++;
1165         }
1166
1167         if (!*s)
1168                 return;
1169
1170         /* I assume that lowercased string takes the same number of bytes
1171          * as source string even in multibyte encoding. (VIV) */
1172         unix_strupper(s,strlen(s)+1,s,strlen(s)+1);     
1173 }
1174
1175 /**
1176  Convert a string to upper case.
1177 **/
1178
1179 char *strdup_upper(const char *s)
1180 {
1181         char *t = strdup(s);
1182         if (t == NULL) {
1183                 DEBUG(0, ("strdup_upper: Out of memory!\n"));
1184                 return NULL;
1185         }
1186         strupper_m(t);
1187         return t;
1188 }
1189
1190 /**
1191  Return a RFC2254 binary string representation of a buffer.
1192  Used in LDAP filters.
1193  Caller must free.
1194 **/
1195
1196 char *binary_string(char *buf, int len)
1197 {
1198         char *s;
1199         int i, j;
1200         const char *hex = "0123456789ABCDEF";
1201         s = malloc(len * 3 + 1);
1202         if (!s)
1203                 return NULL;
1204         for (j=i=0;i<len;i++) {
1205                 s[j] = '\\';
1206                 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1207                 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1208                 j += 3;
1209         }
1210         s[j] = 0;
1211         return s;
1212 }
1213
1214 /**
1215  Just a typesafety wrapper for snprintf into a pstring.
1216 **/
1217
1218  int pstr_sprintf(pstring s, const char *fmt, ...)
1219 {
1220         va_list ap;
1221         int ret;
1222
1223         va_start(ap, fmt);
1224         ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1225         va_end(ap);
1226         return ret;
1227 }
1228
1229
1230 /**
1231  Just a typesafety wrapper for snprintf into a fstring.
1232 **/
1233
1234 int fstr_sprintf(fstring s, const char *fmt, ...)
1235 {
1236         va_list ap;
1237         int ret;
1238
1239         va_start(ap, fmt);
1240         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1241         va_end(ap);
1242         return ret;
1243 }
1244
1245
1246 #ifndef HAVE_STRNDUP
1247 /**
1248  Some platforms don't have strndup.
1249 **/
1250
1251  char *strndup(const char *s, size_t n)
1252 {
1253         char *ret;
1254         
1255         n = strnlen(s, n);
1256         ret = malloc(n+1);
1257         if (!ret)
1258                 return NULL;
1259         memcpy(ret, s, n);
1260         ret[n] = 0;
1261
1262         return ret;
1263 }
1264 #endif
1265
1266 #ifndef HAVE_STRNLEN
1267 /**
1268  Some platforms don't have strnlen
1269 **/
1270
1271  size_t strnlen(const char *s, size_t n)
1272 {
1273         int i;
1274         for (i=0; s[i] && i<n; i++)
1275                 /* noop */ ;
1276         return i;
1277 }
1278 #endif
1279
1280 /**
1281  List of Strings manipulation functions
1282 **/
1283
1284 #define S_LIST_ABS 16 /* List Allocation Block Size */
1285
1286 char **str_list_make(const char *string, const char *sep)
1287 {
1288         char **list, **rlist;
1289         const char *str;
1290         char *s;
1291         int num, lsize;
1292         pstring tok;
1293         
1294         if (!string || !*string)
1295                 return NULL;
1296         s = strdup(string);
1297         if (!s) {
1298                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1299                 return NULL;
1300         }
1301         if (!sep) sep = LIST_SEP;
1302         
1303         num = lsize = 0;
1304         list = NULL;
1305         
1306         str = s;
1307         while (next_token(&str, tok, sep, sizeof(tok))) {               
1308                 if (num == lsize) {
1309                         lsize += S_LIST_ABS;
1310                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1311                         if (!rlist) {
1312                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1313                                 str_list_free(&list);
1314                                 SAFE_FREE(s);
1315                                 return NULL;
1316                         } else
1317                                 list = rlist;
1318                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1319                 }
1320                 
1321                 list[num] = strdup(tok);
1322                 if (!list[num]) {
1323                         DEBUG(0,("str_list_make: Unable to allocate memory"));
1324                         str_list_free(&list);
1325                         SAFE_FREE(s);
1326                         return NULL;
1327                 }
1328         
1329                 num++;  
1330         }
1331         
1332         SAFE_FREE(s);
1333         return list;
1334 }
1335
1336 BOOL str_list_copy(char ***dest, const char **src)
1337 {
1338         char **list, **rlist;
1339         int num, lsize;
1340         
1341         *dest = NULL;
1342         if (!src)
1343                 return False;
1344         
1345         num = lsize = 0;
1346         list = NULL;
1347                 
1348         while (src[num]) {
1349                 if (num == lsize) {
1350                         lsize += S_LIST_ABS;
1351                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1352                         if (!rlist) {
1353                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1354                                 str_list_free(&list);
1355                                 return False;
1356                         } else
1357                                 list = rlist;
1358                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1359                 }
1360                 
1361                 list[num] = strdup(src[num]);
1362                 if (!list[num]) {
1363                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
1364                         str_list_free(&list);
1365                         return False;
1366                 }
1367
1368                 num++;
1369         }
1370         
1371         *dest = list;
1372         return True;    
1373 }
1374
1375 /**
1376  * Return true if all the elements of the list match exactly.
1377  **/
1378 BOOL str_list_compare(char **list1, char **list2)
1379 {
1380         int num;
1381         
1382         if (!list1 || !list2)
1383                 return (list1 == list2); 
1384         
1385         for (num = 0; list1[num]; num++) {
1386                 if (!list2[num])
1387                         return False;
1388                 if (!strcsequal(list1[num], list2[num]))
1389                         return False;
1390         }
1391         if (list2[num])
1392                 return False; /* if list2 has more elements than list1 fail */
1393         
1394         return True;
1395 }
1396
1397 void str_list_free(char ***list)
1398 {
1399         char **tlist;
1400         
1401         if (!list || !*list)
1402                 return;
1403         tlist = *list;
1404         for(; *tlist; tlist++)
1405                 SAFE_FREE(*tlist);
1406         SAFE_FREE(*list);
1407 }
1408
1409 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1410 {
1411         char *p, *s, *t;
1412         ssize_t ls, lp, li, ld, i, d;
1413
1414         if (!list)
1415                 return False;
1416         if (!pattern)
1417                 return False;
1418         if (!insert)
1419                 return False;
1420
1421         lp = (ssize_t)strlen(pattern);
1422         li = (ssize_t)strlen(insert);
1423         ld = li -lp;
1424                         
1425         while (*list) {
1426                 s = *list;
1427                 ls = (ssize_t)strlen(s);
1428
1429                 while ((p = strstr(s, pattern))) {
1430                         t = *list;
1431                         d = p -t;
1432                         if (ld) {
1433                                 t = (char *) malloc(ls +ld +1);
1434                                 if (!t) {
1435                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1436                                         return False;
1437                                 }
1438                                 memcpy(t, *list, d);
1439                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1440                                 SAFE_FREE(*list);
1441                                 *list = t;
1442                                 ls += ld;
1443                                 s = t +d +li;
1444                         }
1445                         
1446                         for (i = 0; i < li; i++) {
1447                                 switch (insert[i]) {
1448                                         case '`':
1449                                         case '"':
1450                                         case '\'':
1451                                         case ';':
1452                                         case '$':
1453                                         case '%':
1454                                         case '\r':
1455                                         case '\n':
1456                                                 t[d +i] = '_';
1457                                                 break;
1458                                         default:
1459                                                 t[d +i] = insert[i];
1460                                 }
1461                         }       
1462                 }
1463                 
1464                 list++;
1465         }
1466         
1467         return True;
1468 }
1469
1470
1471 #define IPSTR_LIST_SEP  ","
1472
1473 /**
1474  * Add ip string representation to ipstr list. Used also
1475  * as part of @function ipstr_list_make
1476  *
1477  * @param ipstr_list pointer to string containing ip list;
1478  *        MUST BE already allocated and IS reallocated if necessary
1479  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1480  *        as a result of reallocation)
1481  * @param ip IP address which is to be added to list
1482  * @return pointer to string appended with new ip and possibly
1483  *         reallocated to new length
1484  **/
1485
1486 char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip)
1487 {
1488         char* new_ipstr = NULL;
1489         
1490         /* arguments checking */
1491         if (!ipstr_list || !ip) return NULL;
1492
1493         /* attempt to convert ip to a string and append colon separator to it */
1494         if (*ipstr_list) {
1495                 asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip));
1496                 SAFE_FREE(*ipstr_list);
1497         } else {
1498                 asprintf(&new_ipstr, "%s", inet_ntoa(*ip));
1499         }
1500         *ipstr_list = new_ipstr;
1501         return *ipstr_list;
1502 }
1503
1504
1505 /**
1506  * Allocate and initialise an ipstr list using ip adresses
1507  * passed as arguments.
1508  *
1509  * @param ipstr_list pointer to string meant to be allocated and set
1510  * @param ip_list array of ip addresses to place in the list
1511  * @param ip_count number of addresses stored in ip_list
1512  * @return pointer to allocated ip string
1513  **/
1514  
1515 char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count)
1516 {
1517         int i;
1518         
1519         /* arguments checking */
1520         if (!ip_list && !ipstr_list) return 0;
1521
1522         *ipstr_list = NULL;
1523         
1524         /* process ip addresses given as arguments */
1525         for (i = 0; i < ip_count; i++)
1526                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1527         
1528         return (*ipstr_list);
1529 }
1530
1531
1532 /**
1533  * Parse given ip string list into array of ip addresses
1534  * (as in_addr structures)
1535  *
1536  * @param ipstr ip string list to be parsed 
1537  * @param ip_list pointer to array of ip addresses which is
1538  *        allocated by this function and must be freed by caller
1539  * @return number of succesfully parsed addresses
1540  **/
1541  
1542 int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list)
1543 {
1544         fstring token_str;
1545         int count;
1546
1547         if (!ipstr_list || !ip_list) return 0;
1548         
1549         for (*ip_list = NULL, count = 0;
1550              next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN);
1551              count++) {
1552              
1553                 struct in_addr addr;
1554
1555                 /* convert single token to ip address */
1556                 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1557                         break;
1558                 
1559                 /* prepare place for another in_addr structure */
1560                 *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr));
1561                 if (!*ip_list) return -1;
1562                 
1563                 (*ip_list)[count] = addr;
1564         }
1565         
1566         return count;
1567 }
1568
1569
1570 /**
1571  * Safely free ip string list
1572  *
1573  * @param ipstr_list ip string list to be freed
1574  **/
1575
1576 void ipstr_list_free(char* ipstr_list)
1577 {
1578         SAFE_FREE(ipstr_list);
1579 }
1580
1581
1582 /**
1583  Unescape a URL encoded string, in place.
1584 **/
1585
1586 void rfc1738_unescape(char *buf)
1587 {
1588         char *p=buf;
1589
1590         while ((p=strchr_m(p,'+')))
1591                 *p = ' ';
1592
1593         p = buf;
1594
1595         while (p && *p && (p=strchr_m(p,'%'))) {
1596                 int c1 = p[1];
1597                 int c2 = p[2];
1598
1599                 if (c1 >= '0' && c1 <= '9')
1600                         c1 = c1 - '0';
1601                 else if (c1 >= 'A' && c1 <= 'F')
1602                         c1 = 10 + c1 - 'A';
1603                 else if (c1 >= 'a' && c1 <= 'f')
1604                         c1 = 10 + c1 - 'a';
1605                 else {p++; continue;}
1606
1607                 if (c2 >= '0' && c2 <= '9')
1608                         c2 = c2 - '0';
1609                 else if (c2 >= 'A' && c2 <= 'F')
1610                         c2 = 10 + c2 - 'A';
1611                 else if (c2 >= 'a' && c2 <= 'f')
1612                         c2 = 10 + c2 - 'a';
1613                 else {p++; continue;}
1614                         
1615                 *p = (c1<<4) | c2;
1616
1617                 memmove(p+1, p+3, strlen(p+3)+1);
1618                 p++;
1619         }
1620 }
1621
1622 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1623
1624 /**
1625  * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
1626  **/
1627 DATA_BLOB base64_decode_data_blob(const char *s)
1628 {
1629         int bit_offset, byte_offset, idx, i, n;
1630         DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1631         unsigned char *d = decoded.data;
1632         char *p;
1633
1634         n=i=0;
1635
1636         while (*s && (p=strchr_m(b64,*s))) {
1637                 idx = (int)(p - b64);
1638                 byte_offset = (i*6)/8;
1639                 bit_offset = (i*6)%8;
1640                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1641                 if (bit_offset < 3) {
1642                         d[byte_offset] |= (idx << (2-bit_offset));
1643                         n = byte_offset+1;
1644                 } else {
1645                         d[byte_offset] |= (idx >> (bit_offset-2));
1646                         d[byte_offset+1] = 0;
1647                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1648                         n = byte_offset+2;
1649                 }
1650                 s++; i++;
1651         }
1652
1653         /* fix up length */
1654         decoded.length = n;
1655         return decoded;
1656 }
1657
1658 /**
1659  * Decode a base64 string in-place - wrapper for the above
1660  **/
1661 void base64_decode_inplace(char *s)
1662 {
1663         DATA_BLOB decoded = base64_decode_data_blob(s);
1664         memcpy(s, decoded.data, decoded.length);
1665         /* null terminate */
1666         s[decoded.length] = '\0';
1667
1668         data_blob_free(&decoded);
1669 }
1670
1671 /**
1672  * Encode a base64 string into a malloc()ed string caller to free.
1673  *
1674  *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
1675  **/
1676 char * base64_encode_data_blob(DATA_BLOB data)
1677 {
1678         int bits = 0;
1679         int char_count = 0;
1680         size_t out_cnt = 0;
1681         size_t len = data.length;
1682         size_t output_len = data.length * 2;
1683         char *result = malloc(output_len); /* get us plenty of space */
1684
1685         while (len-- && out_cnt < (data.length * 2) - 5) {
1686                 int c = (unsigned char) *(data.data++);
1687                 bits += c;
1688                 char_count++;
1689                 if (char_count == 3) {
1690                         result[out_cnt++] = b64[bits >> 18];
1691                         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1692                         result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1693             result[out_cnt++] = b64[bits & 0x3f];
1694             bits = 0;
1695             char_count = 0;
1696         } else {
1697             bits <<= 8;
1698         }
1699     }
1700     if (char_count != 0) {
1701         bits <<= 16 - (8 * char_count);
1702         result[out_cnt++] = b64[bits >> 18];
1703         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1704         if (char_count == 1) {
1705             result[out_cnt++] = '=';
1706             result[out_cnt++] = '=';
1707         } else {
1708             result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1709             result[out_cnt++] = '=';
1710         }
1711     }
1712     result[out_cnt] = '\0';     /* terminate */
1713     return result;
1714 }
1715
1716 /* read a SMB_BIG_UINT from a string */
1717 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1718 {
1719
1720         SMB_BIG_UINT val = -1;
1721         const char *p = nptr;
1722         
1723         while (p && *p && isspace(*p))
1724                 p++;
1725 #ifdef LARGE_SMB_OFF_T
1726         sscanf(p,"%llu",&val);  
1727 #else /* LARGE_SMB_OFF_T */
1728         sscanf(p,"%lu",&val);
1729 #endif /* LARGE_SMB_OFF_T */
1730         if (entptr) {
1731                 while (p && *p && isdigit(*p))
1732                         p++;
1733                 *entptr = p;
1734         }
1735
1736         return val;
1737 }