Fix up overlapping memcpy -> memmove found by valgrind.
[jra/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         char *s;
41         char *pbuf;
42         BOOL quoted;
43         size_t len=1;
44
45         if (!ptr)
46                 return(False);
47
48         s = (char *)*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 = &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=(char *)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=(char *)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 = push_ucs2_allocate(&buffer_s, s);
212         if (size == (size_t)-1) {
213                 return strcmp(s, t); 
214                 /* Not quite the right answer, but finding the right one
215                    under this failure case is expensive, and it's pretty close */
216         }
217         
218         size = push_ucs2_allocate(&buffer_t, t);
219         if (size == (size_t)-1) {
220                 SAFE_FREE(buffer_s);
221                 return strcmp(s, t); 
222                 /* Not quite the right answer, but finding the right one
223                    under this failure case is expensive, and it's pretty close */
224         }
225         
226         ret = strcasecmp_w(buffer_s, buffer_t);
227         SAFE_FREE(buffer_s);
228         SAFE_FREE(buffer_t);
229         return ret;
230 }
231
232
233 /**
234  Case insensitive string compararison, length limited.
235 **/
236 int StrnCaseCmp(const char *s, const char *t, size_t n)
237 {
238         pstring buf1, buf2;
239         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
240         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
241         return strncmp(buf1,buf2,n);
242 }
243
244 /**
245  * Compare 2 strings.
246  *
247  * @note The comparison is case-insensitive.
248  **/
249 BOOL strequal(const char *s1, const char *s2)
250 {
251         if (s1 == s2)
252                 return(True);
253         if (!s1 || !s2)
254                 return(False);
255   
256         return(StrCaseCmp(s1,s2)==0);
257 }
258
259 /**
260  * Compare 2 strings up to and including the nth char.
261  *
262  * @note The comparison is case-insensitive.
263  **/
264 BOOL strnequal(const char *s1,const char *s2,size_t n)
265 {
266   if (s1 == s2)
267           return(True);
268   if (!s1 || !s2 || !n)
269           return(False);
270   
271   return(StrnCaseCmp(s1,s2,n)==0);
272 }
273
274 /**
275  Compare 2 strings (case sensitive).
276 **/
277
278 BOOL strcsequal(const char *s1,const char *s2)
279 {
280   if (s1 == s2)
281           return(True);
282   if (!s1 || !s2)
283           return(False);
284   
285   return(strcmp(s1,s2)==0);
286 }
287
288 /**
289 Do a case-insensitive, whitespace-ignoring string compare.
290 **/
291
292 int strwicmp(const char *psz1, const char *psz2)
293 {
294         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
295         /* appropriate value. */
296         if (psz1 == psz2)
297                 return (0);
298         else if (psz1 == NULL)
299                 return (-1);
300         else if (psz2 == NULL)
301                 return (1);
302
303         /* sync the strings on first non-whitespace */
304         while (1) {
305                 while (isspace((int)*psz1))
306                         psz1++;
307                 while (isspace((int)*psz2))
308                         psz2++;
309                 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
310                     || *psz2 == '\0')
311                         break;
312                 psz1++;
313                 psz2++;
314         }
315         return (*psz1 - *psz2);
316 }
317
318
319 /**
320  Convert a string to upper case, but don't modify it.
321 **/
322
323 char *strupper_static(const char *s)
324 {
325         static pstring str;
326
327         pstrcpy(str, s);
328         strupper_m(str);
329
330         return str;
331 }
332
333 /**
334  Convert a string to "normal" form.
335 **/
336
337 void strnorm(char *s)
338 {
339         extern int case_default;
340         if (case_default == CASE_UPPER)
341                 strupper_m(s);
342         else
343                 strlower_m(s);
344 }
345
346 /**
347  Check if a string is in "normal" case.
348 **/
349
350 BOOL strisnormal(const char *s)
351 {
352         extern int case_default;
353         if (case_default == CASE_UPPER)
354                 return(!strhaslower(s));
355         
356         return(!strhasupper(s));
357 }
358
359
360 /**
361  String replace.
362  NOTE: oldc and newc must be 7 bit characters
363 **/
364
365 void string_replace(pstring s,char oldc,char newc)
366 {
367         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
368         string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
369         pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
370 }
371
372 /**
373  Skip past some strings in a buffer.
374 **/
375
376 char *skip_string(char *buf,size_t n)
377 {
378         while (n--)
379                 buf += strlen(buf) + 1;
380         return(buf);
381 }
382
383 /**
384  Count the number of characters in a string. Normally this will
385  be the same as the number of bytes in a string for single byte strings,
386  but will be different for multibyte.
387 **/
388
389 size_t str_charnum(const char *s)
390 {
391         uint16 tmpbuf2[sizeof(pstring)];
392         push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
393         return strlen_w(tmpbuf2);
394 }
395
396 /**
397  Count the number of characters in a string. Normally this will
398  be the same as the number of bytes in a string for single byte strings,
399  but will be different for multibyte.
400 **/
401
402 size_t str_ascii_charnum(const char *s)
403 {
404         pstring tmpbuf2;
405         push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
406         return strlen(tmpbuf2);
407 }
408
409 /**
410  Trim the specified elements off the front and back of a string.
411 **/
412
413 BOOL trim_string(char *s,const char *front,const char *back)
414 {
415         BOOL ret = False;
416         size_t front_len;
417         size_t back_len;
418         size_t len;
419
420         /* Ignore null or empty strings. */
421         if (!s || (s[0] == '\0'))
422                 return False;
423
424         front_len       = front? strlen(front) : 0;
425         back_len        = back? strlen(back) : 0;
426
427         len = strlen(s);
428
429         if (front_len) {
430                 while (len && strncmp(s, front, front_len)==0) {
431                         /* Must use memmove here as src & dest can
432                          * easily overlap. Found by valgrind. JRA. */
433                         memmove(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                         int offset = PTR_DIFF(s,string);
916                         char *t = Realloc(string, ls + ld + 1);
917                         if (!t) {
918                                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
919                                 SAFE_FREE(in);
920                                 return NULL;
921                         }
922                         string = t;
923                         p = t + offset + (p - s);
924                 }
925                 if (li != lp) {
926                         memmove(p+li,p+lp,strlen(p+lp)+1);
927                 }
928                 memcpy(p, in, li);
929                 s = p + li;
930                 ls += ld;
931         }
932         SAFE_FREE(in);
933         return string;
934 }
935
936 /**
937  Similar to string_sub() but allows for any character to be substituted. 
938  Use with caution!
939  if len==0 then the string cannot be extended. This is different from the old
940  use of len==0 which was for no length checks to be done.
941 **/
942
943 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
944 {
945         char *p;
946         ssize_t ls,lp,li;
947
948         if (!insert || !pattern || !s)
949                 return;
950
951         ls = (ssize_t)strlen(s);
952         lp = (ssize_t)strlen(pattern);
953         li = (ssize_t)strlen(insert);
954
955         if (!*pattern)
956                 return;
957         
958         if (len == 0)
959                 len = ls + 1; /* len is number of *bytes* */
960         
961         while (lp <= ls && (p = strstr(s,pattern))) {
962                 if (ls + (li-lp) >= len) {
963                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
964                                  (int)(ls + (li-lp) - len),
965                                  pattern, (int)len));
966                         break;
967                 }
968                 if (li != lp) {
969                         memmove(p+li,p+lp,strlen(p+lp)+1);
970                 }
971                 memcpy(p, insert, li);
972                 s = p + li;
973                 ls += (li-lp);
974         }
975 }
976
977 /**
978  Similar to all_string_sub but for unicode strings.
979  Return a new allocated unicode string.
980  similar to string_sub() but allows for any character to be substituted.
981  Use with caution!
982 **/
983
984 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
985                                 const smb_ucs2_t *insert)
986 {
987         smb_ucs2_t *r, *rp;
988         const smb_ucs2_t *sp;
989         size_t  lr, lp, li, lt;
990
991         if (!insert || !pattern || !*pattern || !s)
992                 return NULL;
993
994         lt = (size_t)strlen_w(s);
995         lp = (size_t)strlen_w(pattern);
996         li = (size_t)strlen_w(insert);
997
998         if (li > lp) {
999                 const smb_ucs2_t *st = s;
1000                 int ld = li - lp;
1001                 while ((sp = strstr_w(st, pattern))) {
1002                         st = sp + lp;
1003                         lt += ld;
1004                 }
1005         }
1006
1007         r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
1008         if (!r) {
1009                 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
1010                 return NULL;
1011         }
1012
1013         while ((sp = strstr_w(s, pattern))) {
1014                 memcpy(rp, s, (sp - s));
1015                 rp += ((sp - s) / sizeof(smb_ucs2_t));
1016                 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
1017                 s = sp + lp;
1018                 rp += li;
1019         }
1020         lr = ((rp - r) / sizeof(smb_ucs2_t));
1021         if (lr < lt) {
1022                 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
1023                 rp += (lt - lr);
1024         }
1025         *rp = 0;
1026
1027         return r;
1028 }
1029
1030 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
1031                                              const char *insert)
1032 {
1033         wpstring p, i;
1034
1035         if (!insert || !pattern || !s)
1036                 return NULL;
1037         push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1038         push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1039         return all_string_sub_w(s, p, i);
1040 }
1041
1042 #if 0
1043 /**
1044  Splits out the front and back at a separator.
1045 **/
1046
1047 static void split_at_last_component(char *path, char *front, char sep, char *back)
1048 {
1049         char *p = strrchr_m(path, sep);
1050
1051         if (p != NULL)
1052                 *p = 0;
1053
1054         if (front != NULL)
1055                 pstrcpy(front, path);
1056
1057         if (p != NULL) {
1058                 if (back != NULL)
1059                         pstrcpy(back, p+1);
1060                 *p = '\\';
1061         } else {
1062                 if (back != NULL)
1063                         back[0] = 0;
1064         }
1065 }
1066 #endif
1067
1068 /**
1069  Write an octal as a string.
1070 **/
1071
1072 const char *octal_string(int i)
1073 {
1074         static char ret[64];
1075         if (i == -1)
1076                 return "-1";
1077         slprintf(ret, sizeof(ret)-1, "0%o", i);
1078         return ret;
1079 }
1080
1081
1082 /**
1083  Truncate a string at a specified length.
1084 **/
1085
1086 char *string_truncate(char *s, unsigned int length)
1087 {
1088         if (s && strlen(s) > length)
1089                 s[length] = 0;
1090         return s;
1091 }
1092
1093 /**
1094  Strchr and strrchr_m are very hard to do on general multi-byte strings. 
1095  We convert via ucs2 for now.
1096 **/
1097
1098 char *strchr_m(const char *s, char c)
1099 {
1100         wpstring ws;
1101         pstring s2;
1102         smb_ucs2_t *p;
1103
1104         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1105         p = strchr_w(ws, UCS2_CHAR(c));
1106         if (!p)
1107                 return NULL;
1108         *p = 0;
1109         pull_ucs2_pstring(s2, ws);
1110         return (char *)(s+strlen(s2));
1111 }
1112
1113 char *strrchr_m(const char *s, char c)
1114 {
1115         wpstring ws;
1116         pstring s2;
1117         smb_ucs2_t *p;
1118
1119         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1120         p = strrchr_w(ws, UCS2_CHAR(c));
1121         if (!p)
1122                 return NULL;
1123         *p = 0;
1124         pull_ucs2_pstring(s2, ws);
1125         return (char *)(s+strlen(s2));
1126 }
1127
1128 /***********************************************************************
1129  Return the equivalent of doing strrchr 'n' times - always going
1130  backwards.
1131 ***********************************************************************/
1132
1133 char *strnrchr_m(const char *s, char c, unsigned int n)
1134 {
1135         wpstring ws;
1136         pstring s2;
1137         smb_ucs2_t *p;
1138
1139         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1140         p = strnrchr_w(ws, UCS2_CHAR(c), n);
1141         if (!p)
1142                 return NULL;
1143         *p = 0;
1144         pull_ucs2_pstring(s2, ws);
1145         return (char *)(s+strlen(s2));
1146 }
1147
1148 /**
1149  Convert a string to lower case.
1150 **/
1151
1152 void strlower_m(char *s)
1153 {
1154         /* this is quite a common operation, so we want it to be
1155            fast. We optimise for the ascii case, knowing that all our
1156            supported multi-byte character sets are ascii-compatible
1157            (ie. they match for the first 128 chars) */
1158
1159         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1160                 *s = tolower((unsigned char)*s);
1161                 s++;
1162         }
1163
1164         if (!*s)
1165                 return;
1166
1167         /* I assume that lowercased string takes the same number of bytes
1168          * as source string even in UTF-8 encoding. (VIV) */
1169         unix_strlower(s,strlen(s)+1,s,strlen(s)+1);     
1170 }
1171
1172 /**
1173  Convert a string to upper case.
1174 **/
1175
1176 void strupper_m(char *s)
1177 {
1178         /* this is quite a common operation, so we want it to be
1179            fast. We optimise for the ascii case, knowing that all our
1180            supported multi-byte character sets are ascii-compatible
1181            (ie. they match for the first 128 chars) */
1182
1183         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1184                 *s = toupper((unsigned char)*s);
1185                 s++;
1186         }
1187
1188         if (!*s)
1189                 return;
1190
1191         /* I assume that lowercased string takes the same number of bytes
1192          * as source string even in multibyte encoding. (VIV) */
1193         unix_strupper(s,strlen(s)+1,s,strlen(s)+1);     
1194 }
1195
1196 /**
1197  Return a RFC2254 binary string representation of a buffer.
1198  Used in LDAP filters.
1199  Caller must free.
1200 **/
1201
1202 char *binary_string(char *buf, int len)
1203 {
1204         char *s;
1205         int i, j;
1206         const char *hex = "0123456789ABCDEF";
1207         s = malloc(len * 3 + 1);
1208         if (!s)
1209                 return NULL;
1210         for (j=i=0;i<len;i++) {
1211                 s[j] = '\\';
1212                 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1213                 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1214                 j += 3;
1215         }
1216         s[j] = 0;
1217         return s;
1218 }
1219
1220 /**
1221  Just a typesafety wrapper for snprintf into a pstring.
1222 **/
1223
1224  int pstr_sprintf(pstring s, const char *fmt, ...)
1225 {
1226         va_list ap;
1227         int ret;
1228
1229         va_start(ap, fmt);
1230         ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1231         va_end(ap);
1232         return ret;
1233 }
1234
1235
1236 /**
1237  Just a typesafety wrapper for snprintf into a fstring.
1238 **/
1239
1240 int fstr_sprintf(fstring s, const char *fmt, ...)
1241 {
1242         va_list ap;
1243         int ret;
1244
1245         va_start(ap, fmt);
1246         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1247         va_end(ap);
1248         return ret;
1249 }
1250
1251
1252 #ifndef HAVE_STRNDUP
1253 /**
1254  Some platforms don't have strndup.
1255 **/
1256
1257  char *strndup(const char *s, size_t n)
1258 {
1259         char *ret;
1260         
1261         n = strnlen(s, n);
1262         ret = malloc(n+1);
1263         if (!ret)
1264                 return NULL;
1265         memcpy(ret, s, n);
1266         ret[n] = 0;
1267
1268         return ret;
1269 }
1270 #endif
1271
1272 #ifndef HAVE_STRNLEN
1273 /**
1274  Some platforms don't have strnlen
1275 **/
1276
1277  size_t strnlen(const char *s, size_t n)
1278 {
1279         int i;
1280         for (i=0; s[i] && i<n; i++)
1281                 /* noop */ ;
1282         return i;
1283 }
1284 #endif
1285
1286 /**
1287  List of Strings manipulation functions
1288 **/
1289
1290 #define S_LIST_ABS 16 /* List Allocation Block Size */
1291
1292 char **str_list_make(const char *string, const char *sep)
1293 {
1294         char **list, **rlist;
1295         const char *str;
1296         char *s;
1297         int num, lsize;
1298         pstring tok;
1299         
1300         if (!string || !*string)
1301                 return NULL;
1302         s = strdup(string);
1303         if (!s) {
1304                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1305                 return NULL;
1306         }
1307         if (!sep) sep = LIST_SEP;
1308         
1309         num = lsize = 0;
1310         list = NULL;
1311         
1312         str = s;
1313         while (next_token(&str, tok, sep, sizeof(tok))) {               
1314                 if (num == lsize) {
1315                         lsize += S_LIST_ABS;
1316                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1317                         if (!rlist) {
1318                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1319                                 str_list_free(&list);
1320                                 SAFE_FREE(s);
1321                                 return NULL;
1322                         } else
1323                                 list = rlist;
1324                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1325                 }
1326                 
1327                 list[num] = strdup(tok);
1328                 if (!list[num]) {
1329                         DEBUG(0,("str_list_make: Unable to allocate memory"));
1330                         str_list_free(&list);
1331                         SAFE_FREE(s);
1332                         return NULL;
1333                 }
1334         
1335                 num++;  
1336         }
1337         
1338         SAFE_FREE(s);
1339         return list;
1340 }
1341
1342 BOOL str_list_copy(char ***dest, const char **src)
1343 {
1344         char **list, **rlist;
1345         int num, lsize;
1346         
1347         *dest = NULL;
1348         if (!src)
1349                 return False;
1350         
1351         num = lsize = 0;
1352         list = NULL;
1353                 
1354         while (src[num]) {
1355                 if (num == lsize) {
1356                         lsize += S_LIST_ABS;
1357                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1358                         if (!rlist) {
1359                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1360                                 str_list_free(&list);
1361                                 return False;
1362                         } else
1363                                 list = rlist;
1364                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1365                 }
1366                 
1367                 list[num] = strdup(src[num]);
1368                 if (!list[num]) {
1369                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
1370                         str_list_free(&list);
1371                         return False;
1372                 }
1373
1374                 num++;
1375         }
1376         
1377         *dest = list;
1378         return True;    
1379 }
1380
1381 /**
1382  * Return true if all the elements of the list match exactly.
1383  **/
1384 BOOL str_list_compare(char **list1, char **list2)
1385 {
1386         int num;
1387         
1388         if (!list1 || !list2)
1389                 return (list1 == list2); 
1390         
1391         for (num = 0; list1[num]; num++) {
1392                 if (!list2[num])
1393                         return False;
1394                 if (!strcsequal(list1[num], list2[num]))
1395                         return False;
1396         }
1397         if (list2[num])
1398                 return False; /* if list2 has more elements than list1 fail */
1399         
1400         return True;
1401 }
1402
1403 void str_list_free(char ***list)
1404 {
1405         char **tlist;
1406         
1407         if (!list || !*list)
1408                 return;
1409         tlist = *list;
1410         for(; *tlist; tlist++)
1411                 SAFE_FREE(*tlist);
1412         SAFE_FREE(*list);
1413 }
1414
1415 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1416 {
1417         char *p, *s, *t;
1418         ssize_t ls, lp, li, ld, i, d;
1419
1420         if (!list)
1421                 return False;
1422         if (!pattern)
1423                 return False;
1424         if (!insert)
1425                 return False;
1426
1427         lp = (ssize_t)strlen(pattern);
1428         li = (ssize_t)strlen(insert);
1429         ld = li -lp;
1430                         
1431         while (*list) {
1432                 s = *list;
1433                 ls = (ssize_t)strlen(s);
1434
1435                 while ((p = strstr(s, pattern))) {
1436                         t = *list;
1437                         d = p -t;
1438                         if (ld) {
1439                                 t = (char *) malloc(ls +ld +1);
1440                                 if (!t) {
1441                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1442                                         return False;
1443                                 }
1444                                 memcpy(t, *list, d);
1445                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1446                                 SAFE_FREE(*list);
1447                                 *list = t;
1448                                 ls += ld;
1449                                 s = t +d +li;
1450                         }
1451                         
1452                         for (i = 0; i < li; i++) {
1453                                 switch (insert[i]) {
1454                                         case '`':
1455                                         case '"':
1456                                         case '\'':
1457                                         case ';':
1458                                         case '$':
1459                                         case '%':
1460                                         case '\r':
1461                                         case '\n':
1462                                                 t[d +i] = '_';
1463                                                 break;
1464                                         default:
1465                                                 t[d +i] = insert[i];
1466                                 }
1467                         }       
1468                 }
1469                 
1470                 list++;
1471         }
1472         
1473         return True;
1474 }
1475
1476
1477 #define IPSTR_LIST_SEP  ","
1478 #define IPSTR_LIST_CHAR ','
1479
1480 /**
1481  * Add ip string representation to ipstr list. Used also
1482  * as part of @function ipstr_list_make
1483  *
1484  * @param ipstr_list pointer to string containing ip list;
1485  *        MUST BE already allocated and IS reallocated if necessary
1486  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1487  *        as a result of reallocation)
1488  * @param ip IP address which is to be added to list
1489  * @return pointer to string appended with new ip and possibly
1490  *         reallocated to new length
1491  **/
1492
1493 char* ipstr_list_add(char** ipstr_list, const struct ip_service *service)
1494 {
1495         char* new_ipstr = NULL;
1496         
1497         /* arguments checking */
1498         if (!ipstr_list || !service) return NULL;
1499
1500         /* attempt to convert ip to a string and append colon separator to it */
1501         if (*ipstr_list) {
1502                 asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP,
1503                         inet_ntoa(service->ip), service->port);
1504                 SAFE_FREE(*ipstr_list);
1505         } else {
1506                 asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port);
1507         }
1508         *ipstr_list = new_ipstr;
1509         return *ipstr_list;
1510 }
1511
1512
1513 /**
1514  * Allocate and initialise an ipstr list using ip adresses
1515  * passed as arguments.
1516  *
1517  * @param ipstr_list pointer to string meant to be allocated and set
1518  * @param ip_list array of ip addresses to place in the list
1519  * @param ip_count number of addresses stored in ip_list
1520  * @return pointer to allocated ip string
1521  **/
1522  
1523 char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count)
1524 {
1525         int i;
1526         
1527         /* arguments checking */
1528         if (!ip_list && !ipstr_list) return 0;
1529
1530         *ipstr_list = NULL;
1531         
1532         /* process ip addresses given as arguments */
1533         for (i = 0; i < ip_count; i++)
1534                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1535         
1536         return (*ipstr_list);
1537 }
1538
1539
1540 /**
1541  * Parse given ip string list into array of ip addresses
1542  * (as ip_service structures)  
1543  *    e.g. 192.168.1.100:389,192.168.1.78, ...
1544  *
1545  * @param ipstr ip string list to be parsed 
1546  * @param ip_list pointer to array of ip addresses which is
1547  *        allocated by this function and must be freed by caller
1548  * @return number of succesfully parsed addresses
1549  **/
1550  
1551 int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list)
1552 {
1553         fstring token_str;
1554         size_t count;
1555         int i;
1556
1557         if (!ipstr_list || !ip_list) 
1558                 return 0;
1559         
1560         count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1561         if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) {
1562                 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count));
1563                 return 0;
1564         }
1565         
1566         for ( i=0; 
1567                 next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count; 
1568                 i++ ) 
1569         {
1570                 struct in_addr addr;
1571                 unsigned port = 0;      
1572                 char *p = strchr(token_str, ':');
1573                 
1574                 if (p) {
1575                         *p = 0;
1576                         port = atoi(p+1);
1577                 }
1578
1579                 /* convert single token to ip address */
1580                 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1581                         break;
1582                                 
1583                 (*ip_list)[i].ip = addr;
1584                 (*ip_list)[i].port = port;
1585         }
1586         
1587         return count;
1588 }
1589
1590
1591 /**
1592  * Safely free ip string list
1593  *
1594  * @param ipstr_list ip string list to be freed
1595  **/
1596
1597 void ipstr_list_free(char* ipstr_list)
1598 {
1599         SAFE_FREE(ipstr_list);
1600 }
1601
1602
1603 /**
1604  Unescape a URL encoded string, in place.
1605 **/
1606
1607 void rfc1738_unescape(char *buf)
1608 {
1609         char *p=buf;
1610
1611         while ((p=strchr_m(p,'+')))
1612                 *p = ' ';
1613
1614         p = buf;
1615
1616         while (p && *p && (p=strchr_m(p,'%'))) {
1617                 int c1 = p[1];
1618                 int c2 = p[2];
1619
1620                 if (c1 >= '0' && c1 <= '9')
1621                         c1 = c1 - '0';
1622                 else if (c1 >= 'A' && c1 <= 'F')
1623                         c1 = 10 + c1 - 'A';
1624                 else if (c1 >= 'a' && c1 <= 'f')
1625                         c1 = 10 + c1 - 'a';
1626                 else {p++; continue;}
1627
1628                 if (c2 >= '0' && c2 <= '9')
1629                         c2 = c2 - '0';
1630                 else if (c2 >= 'A' && c2 <= 'F')
1631                         c2 = 10 + c2 - 'A';
1632                 else if (c2 >= 'a' && c2 <= 'f')
1633                         c2 = 10 + c2 - 'a';
1634                 else {p++; continue;}
1635                         
1636                 *p = (c1<<4) | c2;
1637
1638                 memmove(p+1, p+3, strlen(p+3)+1);
1639                 p++;
1640         }
1641 }
1642
1643 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1644
1645 /**
1646  * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
1647  **/
1648 DATA_BLOB base64_decode_data_blob(const char *s)
1649 {
1650         int bit_offset, byte_offset, idx, i, n;
1651         DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1652         unsigned char *d = decoded.data;
1653         char *p;
1654
1655         n=i=0;
1656
1657         while (*s && (p=strchr_m(b64,*s))) {
1658                 idx = (int)(p - b64);
1659                 byte_offset = (i*6)/8;
1660                 bit_offset = (i*6)%8;
1661                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1662                 if (bit_offset < 3) {
1663                         d[byte_offset] |= (idx << (2-bit_offset));
1664                         n = byte_offset+1;
1665                 } else {
1666                         d[byte_offset] |= (idx >> (bit_offset-2));
1667                         d[byte_offset+1] = 0;
1668                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1669                         n = byte_offset+2;
1670                 }
1671                 s++; i++;
1672         }
1673
1674         /* fix up length */
1675         decoded.length = n;
1676         return decoded;
1677 }
1678
1679 /**
1680  * Decode a base64 string in-place - wrapper for the above
1681  **/
1682 void base64_decode_inplace(char *s)
1683 {
1684         DATA_BLOB decoded = base64_decode_data_blob(s);
1685         memcpy(s, decoded.data, decoded.length);
1686         /* null terminate */
1687         s[decoded.length] = '\0';
1688
1689         data_blob_free(&decoded);
1690 }
1691
1692 /**
1693  * Encode a base64 string into a malloc()ed string caller to free.
1694  *
1695  *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
1696  **/
1697 char * base64_encode_data_blob(DATA_BLOB data)
1698 {
1699         int bits = 0;
1700         int char_count = 0;
1701         size_t out_cnt = 0;
1702         size_t len = data.length;
1703         size_t output_len = data.length * 2;
1704         char *result = malloc(output_len); /* get us plenty of space */
1705
1706         while (len-- && out_cnt < (data.length * 2) - 5) {
1707                 int c = (unsigned char) *(data.data++);
1708                 bits += c;
1709                 char_count++;
1710                 if (char_count == 3) {
1711                         result[out_cnt++] = b64[bits >> 18];
1712                         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1713                         result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1714             result[out_cnt++] = b64[bits & 0x3f];
1715             bits = 0;
1716             char_count = 0;
1717         } else {
1718             bits <<= 8;
1719         }
1720     }
1721     if (char_count != 0) {
1722         bits <<= 16 - (8 * char_count);
1723         result[out_cnt++] = b64[bits >> 18];
1724         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1725         if (char_count == 1) {
1726             result[out_cnt++] = '=';
1727             result[out_cnt++] = '=';
1728         } else {
1729             result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1730             result[out_cnt++] = '=';
1731         }
1732     }
1733     result[out_cnt] = '\0';     /* terminate */
1734     return result;
1735 }
1736
1737 /* read a SMB_BIG_UINT from a string */
1738 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1739 {
1740
1741         SMB_BIG_UINT val = -1;
1742         const char *p = nptr;
1743         
1744         while (p && *p && isspace(*p))
1745                 p++;
1746 #ifdef LARGE_SMB_OFF_T
1747         sscanf(p,"%llu",&val);  
1748 #else /* LARGE_SMB_OFF_T */
1749         sscanf(p,"%lu",&val);
1750 #endif /* LARGE_SMB_OFF_T */
1751         if (entptr) {
1752                 while (p && *p && isdigit(*p))
1753                         p++;
1754                 *entptr = p;
1755         }
1756
1757         return val;
1758 }