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