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