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