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