fix bug 397: use a variant of alloc_sub_basic() for string lists.
[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 #ifdef DEVELOPER
507         clobber_region(fn,line,dest, maxlength+1);
508 #endif
509
510         if (!src) {
511                 *dest = 0;
512                 return dest;
513         }  
514
515         len = strnlen(src, maxlength+1);
516
517         if (len > maxlength) {
518                 DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
519                          (unsigned int)(len-maxlength), len, maxlength, src));
520                 len = maxlength;
521         }
522       
523         memmove(dest, src, len);
524         dest[len] = 0;
525         return dest;
526 }  
527
528 /**
529  Safe string cat into a string. maxlength does not
530  include the terminating zero.
531 **/
532 char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
533 {
534         size_t src_len, dest_len;
535
536         if (!dest) {
537                 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
538                 return NULL;
539         }
540
541         if (!src)
542                 return dest;
543         
544         src_len = strnlen(src, maxlength + 1);
545         dest_len = strnlen(dest, maxlength + 1);
546
547 #ifdef DEVELOPER
548         clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
549 #endif
550
551         if (src_len + dest_len > maxlength) {
552                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
553                          (int)(src_len + dest_len - maxlength), src));
554                 if (maxlength > dest_len) {
555                         memcpy(&dest[dest_len], src, maxlength - dest_len);
556                 }
557                 dest[maxlength] = 0;
558                 return NULL;
559         }
560
561         memcpy(&dest[dest_len], src, src_len);
562         dest[dest_len + src_len] = 0;
563         return dest;
564 }
565
566 /**
567  Paranoid strcpy into a buffer of given length (includes terminating
568  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
569  and replaces with '_'. Deliberately does *NOT* check for multibyte
570  characters. Don't change it !
571 **/
572 char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
573 {
574         size_t len, i;
575
576 #ifdef DEVELOPER
577         clobber_region(fn, line, dest, maxlength);
578 #endif
579
580         if (!dest) {
581                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
582                 return NULL;
583         }
584
585         if (!src) {
586                 *dest = 0;
587                 return dest;
588         }  
589
590         len = strlen(src);
591         if (len >= maxlength)
592                 len = maxlength - 1;
593
594         if (!other_safe_chars)
595                 other_safe_chars = "";
596
597         for(i = 0; i < len; i++) {
598                 int val = (src[i] & 0xff);
599                 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
600                         dest[i] = src[i];
601                 else
602                         dest[i] = '_';
603         }
604
605         dest[i] = '\0';
606
607         return dest;
608 }
609
610 /**
611  Like strncpy but always null terminates. Make sure there is room!
612  The variable n should always be one less than the available size.
613 **/
614 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
615 {
616         char *d = dest;
617
618 #ifdef DEVELOPER
619         clobber_region(fn, line, dest, n+1);
620 #endif
621
622         if (!dest)
623                 return(NULL);
624         
625         if (!src) {
626                 *dest = 0;
627                 return(dest);
628         }
629         
630         while (n-- && (*d = *src)) {
631                 d++;
632                 src++;
633         }
634
635         *d = 0;
636         return(dest);
637 }
638
639 #if 0
640 /**
641  Like strncpy but copies up to the character marker.  always null terminates.
642  returns a pointer to the character marker in the source string (src).
643 **/
644
645 static char *strncpyn(char *dest, const char *src, size_t n, char c)
646 {
647         char *p;
648         size_t str_len;
649
650 #ifdef DEVELOPER
651         clobber_region(dest, n+1);
652 #endif
653         p = strchr_m(src, c);
654         if (p == NULL) {
655                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
656                 return NULL;
657         }
658
659         str_len = PTR_DIFF(p, src);
660         strncpy(dest, src, MIN(n, str_len));
661         dest[str_len] = '\0';
662
663         return p;
664 }
665 #endif
666
667 /**
668  Routine to get hex characters and turn them into a 16 byte array.
669  the array can be variable length, and any non-hex-numeric
670  characters are skipped.  "0xnn" or "0Xnn" is specially catered
671  for.
672
673  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
674
675 **/
676
677 size_t strhex_to_str(char *p, size_t len, const char *strhex)
678 {
679         size_t i;
680         size_t num_chars = 0;
681         unsigned char   lonybble, hinybble;
682         const char     *hexchars = "0123456789ABCDEF";
683         char           *p1 = NULL, *p2 = NULL;
684
685         for (i = 0; i < len && strhex[i] != 0; i++) {
686                 if (strnequal(hexchars, "0x", 2)) {
687                         i++; /* skip two chars */
688                         continue;
689                 }
690
691                 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
692                         break;
693
694                 i++; /* next hex digit */
695
696                 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
697                         break;
698
699                 /* get the two nybbles */
700                 hinybble = PTR_DIFF(p1, hexchars);
701                 lonybble = PTR_DIFF(p2, hexchars);
702
703                 p[num_chars] = (hinybble << 4) | lonybble;
704                 num_chars++;
705
706                 p1 = NULL;
707                 p2 = NULL;
708         }
709         return num_chars;
710 }
711
712 /**
713  * Routine to print a buffer as HEX digits, into an allocated string.
714  */
715
716 void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
717 {
718         int i;
719         char *hex_buffer;
720
721         *out_hex_buffer = smb_xmalloc((len*2)+1);
722         hex_buffer = *out_hex_buffer;
723
724         for (i = 0; i < len; i++)
725                 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
726 }
727
728 /**
729  Check if a string is part of a list.
730 **/
731
732 BOOL in_list(char *s,char *list,BOOL casesensitive)
733 {
734         pstring tok;
735         const char *p=list;
736
737         if (!list)
738                 return(False);
739
740         while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
741                 if (casesensitive) {
742                         if (strcmp(tok,s) == 0)
743                                 return(True);
744                 } else {
745                         if (StrCaseCmp(tok,s) == 0)
746                                 return(True);
747                 }
748         }
749         return(False);
750 }
751
752 /* this is used to prevent lots of mallocs of size 1 */
753 static char *null_string = NULL;
754
755 /**
756  Set a string value, allocing the space for the string
757 **/
758
759 static BOOL string_init(char **dest,const char *src)
760 {
761         size_t l;
762         if (!src)     
763                 src = "";
764
765         l = strlen(src);
766
767         if (l == 0) {
768                 if (!null_string) {
769                         if((null_string = (char *)malloc(1)) == NULL) {
770                                 DEBUG(0,("string_init: malloc fail for null_string.\n"));
771                                 return False;
772                         }
773                         *null_string = 0;
774                 }
775                 *dest = null_string;
776         } else {
777                 (*dest) = strdup(src);
778                 if ((*dest) == NULL) {
779                         DEBUG(0,("Out of memory in string_init\n"));
780                         return False;
781                 }
782         }
783         return(True);
784 }
785
786 /**
787  Free a string value.
788 **/
789
790 void string_free(char **s)
791 {
792         if (!s || !(*s))
793                 return;
794         if (*s == null_string)
795                 *s = NULL;
796         SAFE_FREE(*s);
797 }
798
799 /**
800  Set a string value, deallocating any existing space, and allocing the space
801  for the string
802 **/
803
804 BOOL string_set(char **dest,const char *src)
805 {
806         string_free(dest);
807         return(string_init(dest,src));
808 }
809
810 /**
811  Substitute a string for a pattern in another string. Make sure there is 
812  enough room!
813
814  This routine looks for pattern in s and replaces it with 
815  insert. It may do multiple replacements.
816
817  Any of " ; ' $ or ` in the insert string are replaced with _
818  if len==0 then the string cannot be extended. This is different from the old
819  use of len==0 which was for no length checks to be done.
820 **/
821
822 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
823 {
824         char *p;
825         ssize_t ls,lp,li, i;
826
827         if (!insert || !pattern || !*pattern || !s)
828                 return;
829
830         ls = (ssize_t)strlen(s);
831         lp = (ssize_t)strlen(pattern);
832         li = (ssize_t)strlen(insert);
833
834         if (len == 0)
835                 len = ls + 1; /* len is number of *bytes* */
836
837         while (lp <= ls && (p = strstr(s,pattern))) {
838                 if (ls + (li-lp) >= len) {
839                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
840                                  (int)(ls + (li-lp) - len),
841                                  pattern, (int)len));
842                         break;
843                 }
844                 if (li != lp) {
845                         memmove(p+li,p+lp,strlen(p+lp)+1);
846                 }
847                 for (i=0;i<li;i++) {
848                         switch (insert[i]) {
849                         case '`':
850                         case '"':
851                         case '\'':
852                         case ';':
853                         case '$':
854                         case '%':
855                         case '\r':
856                         case '\n':
857                                 p[i] = '_';
858                                 break;
859                         default:
860                                 p[i] = insert[i];
861                         }
862                 }
863                 s = p + li;
864                 ls += (li-lp);
865         }
866 }
867
868 void fstring_sub(char *s,const char *pattern,const char *insert)
869 {
870         string_sub(s, pattern, insert, sizeof(fstring));
871 }
872
873 void pstring_sub(char *s,const char *pattern,const char *insert)
874 {
875         string_sub(s, pattern, insert, sizeof(pstring));
876 }
877
878 /**
879  Similar to string_sub, but it will accept only allocated strings
880  and may realloc them so pay attention at what you pass on no
881  pointers inside strings, no pstrings or const may be passed
882  as string.
883 **/
884
885 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
886 {
887         char *p, *in;
888         char *s;
889         ssize_t ls,lp,li,ld, i;
890
891         if (!insert || !pattern || !*pattern || !string || !*string)
892                 return NULL;
893
894         s = string;
895
896         in = strdup(insert);
897         if (!in) {
898                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
899                 return NULL;
900         }
901         ls = (ssize_t)strlen(s);
902         lp = (ssize_t)strlen(pattern);
903         li = (ssize_t)strlen(insert);
904         ld = li - lp;
905         for (i=0;i<li;i++) {
906                 switch (in[i]) {
907                         case '`':
908                         case '"':
909                         case '\'':
910                         case ';':
911                         case '$':
912                         case '%':
913                         case '\r':
914                         case '\n':
915                                 in[i] = '_';
916                         default:
917                                 /* ok */
918                                 break;
919                 }
920         }
921         
922         while ((p = strstr(s,pattern))) {
923                 if (ld > 0) {
924                         int offset = PTR_DIFF(s,string);
925                         char *t = Realloc(string, ls + ld + 1);
926                         if (!t) {
927                                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
928                                 SAFE_FREE(in);
929                                 return NULL;
930                         }
931                         string = t;
932                         p = t + offset + (p - s);
933                 }
934                 if (li != lp) {
935                         memmove(p+li,p+lp,strlen(p+lp)+1);
936                 }
937                 memcpy(p, in, li);
938                 s = p + li;
939                 ls += ld;
940         }
941         SAFE_FREE(in);
942         return string;
943 }
944
945 /**
946  Similar to string_sub() but allows for any character to be substituted. 
947  Use with caution!
948  if len==0 then the string cannot be extended. This is different from the old
949  use of len==0 which was for no length checks to be done.
950 **/
951
952 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
953 {
954         char *p;
955         ssize_t ls,lp,li;
956
957         if (!insert || !pattern || !s)
958                 return;
959
960         ls = (ssize_t)strlen(s);
961         lp = (ssize_t)strlen(pattern);
962         li = (ssize_t)strlen(insert);
963
964         if (!*pattern)
965                 return;
966         
967         if (len == 0)
968                 len = ls + 1; /* len is number of *bytes* */
969         
970         while (lp <= ls && (p = strstr(s,pattern))) {
971                 if (ls + (li-lp) >= len) {
972                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
973                                  (int)(ls + (li-lp) - len),
974                                  pattern, (int)len));
975                         break;
976                 }
977                 if (li != lp) {
978                         memmove(p+li,p+lp,strlen(p+lp)+1);
979                 }
980                 memcpy(p, insert, li);
981                 s = p + li;
982                 ls += (li-lp);
983         }
984 }
985
986 /**
987  Similar to all_string_sub but for unicode strings.
988  Return a new allocated unicode string.
989  similar to string_sub() but allows for any character to be substituted.
990  Use with caution!
991 **/
992
993 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
994                                 const smb_ucs2_t *insert)
995 {
996         smb_ucs2_t *r, *rp;
997         const smb_ucs2_t *sp;
998         size_t  lr, lp, li, lt;
999
1000         if (!insert || !pattern || !*pattern || !s)
1001                 return NULL;
1002
1003         lt = (size_t)strlen_w(s);
1004         lp = (size_t)strlen_w(pattern);
1005         li = (size_t)strlen_w(insert);
1006
1007         if (li > lp) {
1008                 const smb_ucs2_t *st = s;
1009                 int ld = li - lp;
1010                 while ((sp = strstr_w(st, pattern))) {
1011                         st = sp + lp;
1012                         lt += ld;
1013                 }
1014         }
1015
1016         r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
1017         if (!r) {
1018                 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
1019                 return NULL;
1020         }
1021
1022         while ((sp = strstr_w(s, pattern))) {
1023                 memcpy(rp, s, (sp - s));
1024                 rp += ((sp - s) / sizeof(smb_ucs2_t));
1025                 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
1026                 s = sp + lp;
1027                 rp += li;
1028         }
1029         lr = ((rp - r) / sizeof(smb_ucs2_t));
1030         if (lr < lt) {
1031                 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
1032                 rp += (lt - lr);
1033         }
1034         *rp = 0;
1035
1036         return r;
1037 }
1038
1039 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
1040                                              const char *insert)
1041 {
1042         wpstring p, i;
1043
1044         if (!insert || !pattern || !s)
1045                 return NULL;
1046         push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1047         push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1048         return all_string_sub_w(s, p, i);
1049 }
1050
1051 #if 0
1052 /**
1053  Splits out the front and back at a separator.
1054 **/
1055
1056 static void split_at_last_component(char *path, char *front, char sep, char *back)
1057 {
1058         char *p = strrchr_m(path, sep);
1059
1060         if (p != NULL)
1061                 *p = 0;
1062
1063         if (front != NULL)
1064                 pstrcpy(front, path);
1065
1066         if (p != NULL) {
1067                 if (back != NULL)
1068                         pstrcpy(back, p+1);
1069                 *p = '\\';
1070         } else {
1071                 if (back != NULL)
1072                         back[0] = 0;
1073         }
1074 }
1075 #endif
1076
1077 /**
1078  Write an octal as a string.
1079 **/
1080
1081 const char *octal_string(int i)
1082 {
1083         static char ret[64];
1084         if (i == -1)
1085                 return "-1";
1086         slprintf(ret, sizeof(ret)-1, "0%o", i);
1087         return ret;
1088 }
1089
1090
1091 /**
1092  Truncate a string at a specified length.
1093 **/
1094
1095 char *string_truncate(char *s, unsigned int length)
1096 {
1097         if (s && strlen(s) > length)
1098                 s[length] = 0;
1099         return s;
1100 }
1101
1102 /**
1103  Strchr and strrchr_m are very hard to do on general multi-byte strings. 
1104  We convert via ucs2 for now.
1105 **/
1106
1107 char *strchr_m(const char *s, char c)
1108 {
1109         wpstring ws;
1110         pstring s2;
1111         smb_ucs2_t *p;
1112
1113         /* this is quite a common operation, so we want it to be
1114            fast. We optimise for the ascii case, knowing that all our
1115            supported multi-byte character sets are ascii-compatible
1116            (ie. they match for the first 128 chars) */
1117
1118         while (*s && (((unsigned char)s[0]) & 0x80)) {
1119                 if (*s == c)
1120                         return s;
1121         }
1122
1123         if (!*s)
1124                 return NULL;
1125
1126         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1127         p = strchr_w(ws, UCS2_CHAR(c));
1128         if (!p)
1129                 return NULL;
1130         *p = 0;
1131         pull_ucs2_pstring(s2, ws);
1132         return (char *)(s+strlen(s2));
1133 }
1134
1135 char *strrchr_m(const char *s, char c)
1136 {
1137         /* this is quite a common operation, so we want it to be
1138            fast. We optimise for the ascii case, knowing that all our
1139            supported multi-byte character sets are ascii-compatible
1140            (ie. they match for the first 128 chars). Also, in Samba
1141            we only search for ascii characters in 'c' and that
1142            in all mb character sets with a compound character
1143            containing c, if 'c' is not a match at position
1144            p, then p[-1] > 0x7f. JRA. */
1145
1146         {
1147                 size_t len = strlen(s);
1148                 const char *cp = s;
1149                 BOOL got_mb = False;
1150
1151                 if (len == 0)
1152                         return NULL;
1153                 cp += (len - 1);
1154                 do {
1155                         if (c == *cp) {
1156                                 /* Could be a match. Part of a multibyte ? */
1157                                 if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
1158                                         /* Yep - go slow :-( */
1159                                         got_mb = True;
1160                                         break;
1161                                 }
1162                                 /* No - we have a match ! */
1163                                 return cp;
1164                         }
1165                 } while (cp-- != s);
1166                 if (!got_mb)
1167                         return NULL;
1168         }
1169
1170         /* String contained a non-ascii char. Slow path. */
1171         {
1172                 wpstring ws;
1173                 pstring s2;
1174                 smb_ucs2_t *p;
1175
1176                 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1177                 p = strrchr_w(ws, UCS2_CHAR(c));
1178                 if (!p)
1179                         return NULL;
1180                 *p = 0;
1181                 pull_ucs2_pstring(s2, ws);
1182                 return (char *)(s+strlen(s2));
1183         }
1184 }
1185
1186 /***********************************************************************
1187  Return the equivalent of doing strrchr 'n' times - always going
1188  backwards.
1189 ***********************************************************************/
1190
1191 char *strnrchr_m(const char *s, char c, unsigned int n)
1192 {
1193         wpstring ws;
1194         pstring s2;
1195         smb_ucs2_t *p;
1196
1197         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1198         p = strnrchr_w(ws, UCS2_CHAR(c), n);
1199         if (!p)
1200                 return NULL;
1201         *p = 0;
1202         pull_ucs2_pstring(s2, ws);
1203         return (char *)(s+strlen(s2));
1204 }
1205
1206 /**
1207  Convert a string to lower case.
1208 **/
1209
1210 void strlower_m(char *s)
1211 {
1212         /* this is quite a common operation, so we want it to be
1213            fast. We optimise for the ascii case, knowing that all our
1214            supported multi-byte character sets are ascii-compatible
1215            (ie. they match for the first 128 chars) */
1216
1217         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1218                 *s = tolower((unsigned char)*s);
1219                 s++;
1220         }
1221
1222         if (!*s)
1223                 return;
1224
1225         /* I assume that lowercased string takes the same number of bytes
1226          * as source string even in UTF-8 encoding. (VIV) */
1227         unix_strlower(s,strlen(s)+1,s,strlen(s)+1);     
1228 }
1229
1230 /**
1231  Convert a string to upper case.
1232 **/
1233
1234 void strupper_m(char *s)
1235 {
1236         /* this is quite a common operation, so we want it to be
1237            fast. We optimise for the ascii case, knowing that all our
1238            supported multi-byte character sets are ascii-compatible
1239            (ie. they match for the first 128 chars) */
1240
1241         while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1242                 *s = toupper((unsigned char)*s);
1243                 s++;
1244         }
1245
1246         if (!*s)
1247                 return;
1248
1249         /* I assume that lowercased string takes the same number of bytes
1250          * as source string even in multibyte encoding. (VIV) */
1251         unix_strupper(s,strlen(s)+1,s,strlen(s)+1);     
1252 }
1253
1254 /**
1255  Return a RFC2254 binary string representation of a buffer.
1256  Used in LDAP filters.
1257  Caller must free.
1258 **/
1259
1260 char *binary_string(char *buf, int len)
1261 {
1262         char *s;
1263         int i, j;
1264         const char *hex = "0123456789ABCDEF";
1265         s = malloc(len * 3 + 1);
1266         if (!s)
1267                 return NULL;
1268         for (j=i=0;i<len;i++) {
1269                 s[j] = '\\';
1270                 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1271                 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1272                 j += 3;
1273         }
1274         s[j] = 0;
1275         return s;
1276 }
1277
1278 /**
1279  Just a typesafety wrapper for snprintf into a pstring.
1280 **/
1281
1282  int pstr_sprintf(pstring s, const char *fmt, ...)
1283 {
1284         va_list ap;
1285         int ret;
1286
1287         va_start(ap, fmt);
1288         ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1289         va_end(ap);
1290         return ret;
1291 }
1292
1293
1294 /**
1295  Just a typesafety wrapper for snprintf into a fstring.
1296 **/
1297
1298 int fstr_sprintf(fstring s, const char *fmt, ...)
1299 {
1300         va_list ap;
1301         int ret;
1302
1303         va_start(ap, fmt);
1304         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1305         va_end(ap);
1306         return ret;
1307 }
1308
1309
1310 #ifndef HAVE_STRNDUP
1311 /**
1312  Some platforms don't have strndup.
1313 **/
1314
1315  char *strndup(const char *s, size_t n)
1316 {
1317         char *ret;
1318         
1319         n = strnlen(s, n);
1320         ret = malloc(n+1);
1321         if (!ret)
1322                 return NULL;
1323         memcpy(ret, s, n);
1324         ret[n] = 0;
1325
1326         return ret;
1327 }
1328 #endif
1329
1330 #ifndef HAVE_STRNLEN
1331 /**
1332  Some platforms don't have strnlen
1333 **/
1334
1335  size_t strnlen(const char *s, size_t n)
1336 {
1337         int i;
1338         for (i=0; s[i] && i<n; i++)
1339                 /* noop */ ;
1340         return i;
1341 }
1342 #endif
1343
1344 /**
1345  List of Strings manipulation functions
1346 **/
1347
1348 #define S_LIST_ABS 16 /* List Allocation Block Size */
1349
1350 char **str_list_make(const char *string, const char *sep)
1351 {
1352         char **list, **rlist;
1353         const char *str;
1354         char *s;
1355         int num, lsize;
1356         pstring tok;
1357         
1358         if (!string || !*string)
1359                 return NULL;
1360         s = strdup(string);
1361         if (!s) {
1362                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1363                 return NULL;
1364         }
1365         if (!sep) sep = LIST_SEP;
1366         
1367         num = lsize = 0;
1368         list = NULL;
1369         
1370         str = s;
1371         while (next_token(&str, tok, sep, sizeof(tok))) {               
1372                 if (num == lsize) {
1373                         lsize += S_LIST_ABS;
1374                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1375                         if (!rlist) {
1376                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1377                                 str_list_free(&list);
1378                                 SAFE_FREE(s);
1379                                 return NULL;
1380                         } else
1381                                 list = rlist;
1382                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1383                 }
1384                 
1385                 list[num] = strdup(tok);
1386                 if (!list[num]) {
1387                         DEBUG(0,("str_list_make: Unable to allocate memory"));
1388                         str_list_free(&list);
1389                         SAFE_FREE(s);
1390                         return NULL;
1391                 }
1392         
1393                 num++;  
1394         }
1395         
1396         SAFE_FREE(s);
1397         return list;
1398 }
1399
1400 BOOL str_list_copy(char ***dest, const char **src)
1401 {
1402         char **list, **rlist;
1403         int num, lsize;
1404         
1405         *dest = NULL;
1406         if (!src)
1407                 return False;
1408         
1409         num = lsize = 0;
1410         list = NULL;
1411                 
1412         while (src[num]) {
1413                 if (num == lsize) {
1414                         lsize += S_LIST_ABS;
1415                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1416                         if (!rlist) {
1417                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1418                                 str_list_free(&list);
1419                                 return False;
1420                         } else
1421                                 list = rlist;
1422                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1423                 }
1424                 
1425                 list[num] = strdup(src[num]);
1426                 if (!list[num]) {
1427                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
1428                         str_list_free(&list);
1429                         return False;
1430                 }
1431
1432                 num++;
1433         }
1434         
1435         *dest = list;
1436         return True;    
1437 }
1438
1439 /**
1440  * Return true if all the elements of the list match exactly.
1441  **/
1442 BOOL str_list_compare(char **list1, char **list2)
1443 {
1444         int num;
1445         
1446         if (!list1 || !list2)
1447                 return (list1 == list2); 
1448         
1449         for (num = 0; list1[num]; num++) {
1450                 if (!list2[num])
1451                         return False;
1452                 if (!strcsequal(list1[num], list2[num]))
1453                         return False;
1454         }
1455         if (list2[num])
1456                 return False; /* if list2 has more elements than list1 fail */
1457         
1458         return True;
1459 }
1460
1461 void str_list_free(char ***list)
1462 {
1463         char **tlist;
1464         
1465         if (!list || !*list)
1466                 return;
1467         tlist = *list;
1468         for(; *tlist; tlist++)
1469                 SAFE_FREE(*tlist);
1470         SAFE_FREE(*list);
1471 }
1472
1473 /******************************************************************************
1474  version of standard_sub_basic() for string lists; uses alloc_sub_basic() 
1475  for the work
1476  *****************************************************************************/
1477  
1478 BOOL str_list_sub_basic( char **list, const char *smb_name )
1479 {
1480         char *s, *tmpstr;
1481         
1482         while ( *list ) {
1483                 s = *list;
1484                 tmpstr = alloc_sub_basic(smb_name, s);
1485                 if ( !tmpstr ) {
1486                         DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
1487                         return False;
1488                 }
1489
1490                 *list = tmpstr;
1491                         
1492                 list++;
1493         }
1494
1495         return True;
1496 }
1497
1498 /******************************************************************************
1499  substritute a specific pattern in a string list
1500  *****************************************************************************/
1501  
1502 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1503 {
1504         char *p, *s, *t;
1505         ssize_t ls, lp, li, ld, i, d;
1506
1507         if (!list)
1508                 return False;
1509         if (!pattern)
1510                 return False;
1511         if (!insert)
1512                 return False;
1513
1514         lp = (ssize_t)strlen(pattern);
1515         li = (ssize_t)strlen(insert);
1516         ld = li -lp;
1517                         
1518         while (*list) {
1519                 s = *list;
1520                 ls = (ssize_t)strlen(s);
1521
1522                 while ((p = strstr(s, pattern))) {
1523                         t = *list;
1524                         d = p -t;
1525                         if (ld) {
1526                                 t = (char *) malloc(ls +ld +1);
1527                                 if (!t) {
1528                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1529                                         return False;
1530                                 }
1531                                 memcpy(t, *list, d);
1532                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1533                                 SAFE_FREE(*list);
1534                                 *list = t;
1535                                 ls += ld;
1536                                 s = t +d +li;
1537                         }
1538                         
1539                         for (i = 0; i < li; i++) {
1540                                 switch (insert[i]) {
1541                                         case '`':
1542                                         case '"':
1543                                         case '\'':
1544                                         case ';':
1545                                         case '$':
1546                                         case '%':
1547                                         case '\r':
1548                                         case '\n':
1549                                                 t[d +i] = '_';
1550                                                 break;
1551                                         default:
1552                                                 t[d +i] = insert[i];
1553                                 }
1554                         }       
1555                 }
1556                 
1557                 
1558                 list++;
1559         }
1560         
1561         return True;
1562 }
1563
1564
1565 #define IPSTR_LIST_SEP  ","
1566 #define IPSTR_LIST_CHAR ','
1567
1568 /**
1569  * Add ip string representation to ipstr list. Used also
1570  * as part of @function ipstr_list_make
1571  *
1572  * @param ipstr_list pointer to string containing ip list;
1573  *        MUST BE already allocated and IS reallocated if necessary
1574  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1575  *        as a result of reallocation)
1576  * @param ip IP address which is to be added to list
1577  * @return pointer to string appended with new ip and possibly
1578  *         reallocated to new length
1579  **/
1580
1581 char* ipstr_list_add(char** ipstr_list, const struct ip_service *service)
1582 {
1583         char* new_ipstr = NULL;
1584         
1585         /* arguments checking */
1586         if (!ipstr_list || !service) return NULL;
1587
1588         /* attempt to convert ip to a string and append colon separator to it */
1589         if (*ipstr_list) {
1590                 asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP,
1591                         inet_ntoa(service->ip), service->port);
1592                 SAFE_FREE(*ipstr_list);
1593         } else {
1594                 asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port);
1595         }
1596         *ipstr_list = new_ipstr;
1597         return *ipstr_list;
1598 }
1599
1600
1601 /**
1602  * Allocate and initialise an ipstr list using ip adresses
1603  * passed as arguments.
1604  *
1605  * @param ipstr_list pointer to string meant to be allocated and set
1606  * @param ip_list array of ip addresses to place in the list
1607  * @param ip_count number of addresses stored in ip_list
1608  * @return pointer to allocated ip string
1609  **/
1610  
1611 char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count)
1612 {
1613         int i;
1614         
1615         /* arguments checking */
1616         if (!ip_list && !ipstr_list) return 0;
1617
1618         *ipstr_list = NULL;
1619         
1620         /* process ip addresses given as arguments */
1621         for (i = 0; i < ip_count; i++)
1622                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1623         
1624         return (*ipstr_list);
1625 }
1626
1627
1628 /**
1629  * Parse given ip string list into array of ip addresses
1630  * (as ip_service structures)  
1631  *    e.g. 192.168.1.100:389,192.168.1.78, ...
1632  *
1633  * @param ipstr ip string list to be parsed 
1634  * @param ip_list pointer to array of ip addresses which is
1635  *        allocated by this function and must be freed by caller
1636  * @return number of succesfully parsed addresses
1637  **/
1638  
1639 int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list)
1640 {
1641         fstring token_str;
1642         size_t count;
1643         int i;
1644
1645         if (!ipstr_list || !ip_list) 
1646                 return 0;
1647         
1648         count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1649         if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) {
1650                 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count));
1651                 return 0;
1652         }
1653         
1654         for ( i=0; 
1655                 next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count; 
1656                 i++ ) 
1657         {
1658                 struct in_addr addr;
1659                 unsigned port = 0;      
1660                 char *p = strchr(token_str, ':');
1661                 
1662                 if (p) {
1663                         *p = 0;
1664                         port = atoi(p+1);
1665                 }
1666
1667                 /* convert single token to ip address */
1668                 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1669                         break;
1670                                 
1671                 (*ip_list)[i].ip = addr;
1672                 (*ip_list)[i].port = port;
1673         }
1674         
1675         return count;
1676 }
1677
1678
1679 /**
1680  * Safely free ip string list
1681  *
1682  * @param ipstr_list ip string list to be freed
1683  **/
1684
1685 void ipstr_list_free(char* ipstr_list)
1686 {
1687         SAFE_FREE(ipstr_list);
1688 }
1689
1690
1691 /**
1692  Unescape a URL encoded string, in place.
1693 **/
1694
1695 void rfc1738_unescape(char *buf)
1696 {
1697         char *p=buf;
1698
1699         while ((p=strchr_m(p,'+')))
1700                 *p = ' ';
1701
1702         p = buf;
1703
1704         while (p && *p && (p=strchr_m(p,'%'))) {
1705                 int c1 = p[1];
1706                 int c2 = p[2];
1707
1708                 if (c1 >= '0' && c1 <= '9')
1709                         c1 = c1 - '0';
1710                 else if (c1 >= 'A' && c1 <= 'F')
1711                         c1 = 10 + c1 - 'A';
1712                 else if (c1 >= 'a' && c1 <= 'f')
1713                         c1 = 10 + c1 - 'a';
1714                 else {p++; continue;}
1715
1716                 if (c2 >= '0' && c2 <= '9')
1717                         c2 = c2 - '0';
1718                 else if (c2 >= 'A' && c2 <= 'F')
1719                         c2 = 10 + c2 - 'A';
1720                 else if (c2 >= 'a' && c2 <= 'f')
1721                         c2 = 10 + c2 - 'a';
1722                 else {p++; continue;}
1723                         
1724                 *p = (c1<<4) | c2;
1725
1726                 memmove(p+1, p+3, strlen(p+3)+1);
1727                 p++;
1728         }
1729 }
1730
1731 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1732
1733 /**
1734  * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
1735  **/
1736 DATA_BLOB base64_decode_data_blob(const char *s)
1737 {
1738         int bit_offset, byte_offset, idx, i, n;
1739         DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1740         unsigned char *d = decoded.data;
1741         char *p;
1742
1743         n=i=0;
1744
1745         while (*s && (p=strchr_m(b64,*s))) {
1746                 idx = (int)(p - b64);
1747                 byte_offset = (i*6)/8;
1748                 bit_offset = (i*6)%8;
1749                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1750                 if (bit_offset < 3) {
1751                         d[byte_offset] |= (idx << (2-bit_offset));
1752                         n = byte_offset+1;
1753                 } else {
1754                         d[byte_offset] |= (idx >> (bit_offset-2));
1755                         d[byte_offset+1] = 0;
1756                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1757                         n = byte_offset+2;
1758                 }
1759                 s++; i++;
1760         }
1761
1762         /* fix up length */
1763         decoded.length = n;
1764         return decoded;
1765 }
1766
1767 /**
1768  * Decode a base64 string in-place - wrapper for the above
1769  **/
1770 void base64_decode_inplace(char *s)
1771 {
1772         DATA_BLOB decoded = base64_decode_data_blob(s);
1773         memcpy(s, decoded.data, decoded.length);
1774         /* null terminate */
1775         s[decoded.length] = '\0';
1776
1777         data_blob_free(&decoded);
1778 }
1779
1780 /**
1781  * Encode a base64 string into a malloc()ed string caller to free.
1782  *
1783  *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
1784  **/
1785 char * base64_encode_data_blob(DATA_BLOB data)
1786 {
1787         int bits = 0;
1788         int char_count = 0;
1789         size_t out_cnt = 0;
1790         size_t len = data.length;
1791         size_t output_len = data.length * 2;
1792         char *result = malloc(output_len); /* get us plenty of space */
1793
1794         while (len-- && out_cnt < (data.length * 2) - 5) {
1795                 int c = (unsigned char) *(data.data++);
1796                 bits += c;
1797                 char_count++;
1798                 if (char_count == 3) {
1799                         result[out_cnt++] = b64[bits >> 18];
1800                         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1801                         result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1802             result[out_cnt++] = b64[bits & 0x3f];
1803             bits = 0;
1804             char_count = 0;
1805         } else {
1806             bits <<= 8;
1807         }
1808     }
1809     if (char_count != 0) {
1810         bits <<= 16 - (8 * char_count);
1811         result[out_cnt++] = b64[bits >> 18];
1812         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1813         if (char_count == 1) {
1814             result[out_cnt++] = '=';
1815             result[out_cnt++] = '=';
1816         } else {
1817             result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1818             result[out_cnt++] = '=';
1819         }
1820     }
1821     result[out_cnt] = '\0';     /* terminate */
1822     return result;
1823 }
1824
1825 /* read a SMB_BIG_UINT from a string */
1826 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1827 {
1828
1829         SMB_BIG_UINT val = -1;
1830         const char *p = nptr;
1831         
1832         while (p && *p && isspace(*p))
1833                 p++;
1834 #ifdef LARGE_SMB_OFF_T
1835         sscanf(p,"%llu",&val);  
1836 #else /* LARGE_SMB_OFF_T */
1837         sscanf(p,"%lu",&val);
1838 #endif /* LARGE_SMB_OFF_T */
1839         if (entptr) {
1840                 while (p && *p && isdigit(*p))
1841                         p++;
1842                 *entptr = p;
1843         }
1844
1845         return val;
1846 }