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