r16554: Sorry, just had to change this. Don't use int when
[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  * Internal function to get the next token from a string, return False if none
33  * found.  Handles double-quotes.  This is the work horse function called by
34  * next_token() and next_token_no_ltrim().
35  *
36  * Based on a routine by GJC@VILLAGE.COM. 
37  * Extensively modified by Andrew.Tridgell@anu.edu.au
38  */
39 static BOOL next_token_internal(const char **ptr,
40                                 char *buff,
41                                 const char *sep,
42                                 size_t bufsize,
43                                 BOOL ltrim)
44 {
45         char *s;
46         char *pbuf;
47         BOOL quoted;
48         size_t len=1;
49
50         if (!ptr)
51                 return(False);
52
53         s = (char *)*ptr;
54
55         /* default to simple separators */
56         if (!sep)
57                 sep = " \t\n\r";
58
59         /* find the first non sep char, if left-trimming is requested */
60         if (ltrim) {
61                 while (*s && strchr_m(sep,*s))
62                         s++;
63         }
64         
65         /* nothing left? */
66         if (! *s)
67                 return(False);
68         
69         /* copy over the token */
70         pbuf = buff;
71         for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
72                 if ( *s == '\"' ) {
73                         quoted = !quoted;
74                 } else {
75                         len++;
76                         *pbuf++ = *s;
77                 }
78         }
79         
80         *ptr = (*s) ? s+1 : s;  
81         *pbuf = 0;
82         
83         return(True);
84 }
85
86 /*
87  * Get the next token from a string, return False if none found.  Handles
88  * double-quotes.  This version trims leading separator characters before
89  * looking for a token.
90  */
91 BOOL next_token(const char **ptr, char *buff, const char *sep, size_t bufsize)
92 {
93     return next_token_internal(ptr, buff, sep, bufsize, True);
94 }
95
96 /*
97  * Get the next token from a string, return False if none found.  Handles
98  * double-quotes.  This version does not trim leading separator characters
99  * before looking for a token.
100  */
101 BOOL next_token_no_ltrim(const char **ptr,
102                          char *buff,
103                          const char *sep,
104                          size_t bufsize)
105 {
106     return next_token_internal(ptr, buff, sep, bufsize, False);
107 }
108
109 /**
110 This is like next_token but is not re-entrant and "remembers" the first 
111 parameter so you can pass NULL. This is useful for user interface code
112 but beware the fact that it is not re-entrant!
113 **/
114
115 static const char *last_ptr=NULL;
116
117 BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
118 {
119         BOOL ret;
120         if (!ptr)
121                 ptr = &last_ptr;
122
123         ret = next_token(ptr, buff, sep, bufsize);
124         last_ptr = *ptr;
125         return ret;     
126 }
127
128 static uint16 tmpbuf[sizeof(pstring)];
129
130 void set_first_token(char *ptr)
131 {
132         last_ptr = ptr;
133 }
134
135 /**
136  Convert list of tokens to array; dependent on above routine.
137  Uses last_ptr from above - bit of a hack.
138 **/
139
140 char **toktocliplist(int *ctok, const char *sep)
141 {
142         char *s=(char *)last_ptr;
143         int ictok=0;
144         char **ret, **iret;
145
146         if (!sep)
147                 sep = " \t\n\r";
148
149         while(*s && strchr_m(sep,*s))
150                 s++;
151
152         /* nothing left? */
153         if (!*s)
154                 return(NULL);
155
156         do {
157                 ictok++;
158                 while(*s && (!strchr_m(sep,*s)))
159                         s++;
160                 while(*s && strchr_m(sep,*s))
161                         *s++=0;
162         } while(*s);
163         
164         *ctok=ictok;
165         s=(char *)last_ptr;
166         
167         if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1)))
168                 return NULL;
169         
170         while(ictok--) {    
171                 *iret++=s;
172                 if (ictok > 0) {
173                         while(*s++)
174                                 ;
175                         while(!*s)
176                                 s++;
177                 }
178         }
179
180         ret[*ctok] = NULL;
181         return ret;
182 }
183
184 /**
185  * Case insensitive string compararison.
186  *
187  * iconv does not directly give us a way to compare strings in
188  * arbitrary unix character sets -- all we can is convert and then
189  * compare.  This is expensive.
190  *
191  * As an optimization, we do a first pass that considers only the
192  * prefix of the strings that is entirely 7-bit.  Within this, we
193  * check whether they have the same value.
194  *
195  * Hopefully this will often give the answer without needing to copy.
196  * In particular it should speed comparisons to literal ascii strings
197  * or comparisons of strings that are "obviously" different.
198  *
199  * If we find a non-ascii character we fall back to converting via
200  * iconv.
201  *
202  * This should never be slower than convering the whole thing, and
203  * often faster.
204  *
205  * A different optimization would be to compare for bitwise equality
206  * in the binary encoding.  (It would be possible thought hairy to do
207  * both simultaneously.)  But in that case if they turn out to be
208  * different, we'd need to restart the whole thing.
209  *
210  * Even better is to implement strcasecmp for each encoding and use a
211  * function pointer. 
212  **/
213 int StrCaseCmp(const char *s, const char *t)
214 {
215
216         const char *ps, *pt;
217         size_t size;
218         smb_ucs2_t *buffer_s, *buffer_t;
219         int ret;
220
221         for (ps = s, pt = t; ; ps++, pt++) {
222                 char us, ut;
223
224                 if (!*ps && !*pt)
225                         return 0; /* both ended */
226                 else if (!*ps)
227                         return -1; /* s is a prefix */
228                 else if (!*pt)
229                         return +1; /* t is a prefix */
230                 else if ((*ps & 0x80) || (*pt & 0x80))
231                         /* not ascii anymore, do it the hard way from here on in */
232                         break;
233
234                 us = toupper_ascii(*ps);
235                 ut = toupper_ascii(*pt);
236                 if (us == ut)
237                         continue;
238                 else if (us < ut)
239                         return -1;
240                 else if (us > ut)
241                         return +1;
242         }
243
244         size = push_ucs2_allocate(&buffer_s, ps);
245         if (size == (size_t)-1) {
246                 return strcmp(ps, pt); 
247                 /* Not quite the right answer, but finding the right one
248                    under this failure case is expensive, and it's pretty close */
249         }
250         
251         size = push_ucs2_allocate(&buffer_t, pt);
252         if (size == (size_t)-1) {
253                 SAFE_FREE(buffer_s);
254                 return strcmp(ps, pt); 
255                 /* Not quite the right answer, but finding the right one
256                    under this failure case is expensive, and it's pretty close */
257         }
258         
259         ret = strcasecmp_w(buffer_s, buffer_t);
260         SAFE_FREE(buffer_s);
261         SAFE_FREE(buffer_t);
262         return ret;
263 }
264
265
266 /**
267  Case insensitive string compararison, length limited.
268 **/
269 int StrnCaseCmp(const char *s, const char *t, size_t n)
270 {
271         pstring buf1, buf2;
272         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
273         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
274         return strncmp(buf1,buf2,n);
275 }
276
277 /**
278  * Compare 2 strings.
279  *
280  * @note The comparison is case-insensitive.
281  **/
282 BOOL strequal(const char *s1, const char *s2)
283 {
284         if (s1 == s2)
285                 return(True);
286         if (!s1 || !s2)
287                 return(False);
288   
289         return(StrCaseCmp(s1,s2)==0);
290 }
291
292 /**
293  * Compare 2 strings up to and including the nth char.
294  *
295  * @note The comparison is case-insensitive.
296  **/
297 BOOL strnequal(const char *s1,const char *s2,size_t n)
298 {
299         if (s1 == s2)
300                 return(True);
301         if (!s1 || !s2 || !n)
302                 return(False);
303   
304         return(StrnCaseCmp(s1,s2,n)==0);
305 }
306
307 /**
308  Compare 2 strings (case sensitive).
309 **/
310
311 BOOL strcsequal(const char *s1,const char *s2)
312 {
313         if (s1 == s2)
314                 return(True);
315         if (!s1 || !s2)
316                 return(False);
317   
318         return(strcmp(s1,s2)==0);
319 }
320
321 /**
322 Do a case-insensitive, whitespace-ignoring string compare.
323 **/
324
325 int strwicmp(const char *psz1, const char *psz2)
326 {
327         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
328         /* appropriate value. */
329         if (psz1 == psz2)
330                 return (0);
331         else if (psz1 == NULL)
332                 return (-1);
333         else if (psz2 == NULL)
334                 return (1);
335
336         /* sync the strings on first non-whitespace */
337         while (1) {
338                 while (isspace((int)*psz1))
339                         psz1++;
340                 while (isspace((int)*psz2))
341                         psz2++;
342                 if (toupper_ascii(*psz1) != toupper_ascii(*psz2) || *psz1 == '\0'
343                     || *psz2 == '\0')
344                         break;
345                 psz1++;
346                 psz2++;
347         }
348         return (*psz1 - *psz2);
349 }
350
351
352 /**
353  Convert a string to upper case, but don't modify it.
354 **/
355
356 char *strupper_static(const char *s)
357 {
358         static pstring str;
359
360         pstrcpy(str, s);
361         strupper_m(str);
362
363         return str;
364 }
365
366 /**
367  Convert a string to "normal" form.
368 **/
369
370 void strnorm(char *s, int case_default)
371 {
372         if (case_default == CASE_UPPER)
373                 strupper_m(s);
374         else
375                 strlower_m(s);
376 }
377
378 /**
379  Check if a string is in "normal" case.
380 **/
381
382 BOOL strisnormal(const char *s, int case_default)
383 {
384         if (case_default == CASE_UPPER)
385                 return(!strhaslower(s));
386         
387         return(!strhasupper(s));
388 }
389
390
391 /**
392  String replace.
393  NOTE: oldc and newc must be 7 bit characters
394 **/
395
396 void string_replace( pstring s, char oldc, char newc )
397 {
398         char *p;
399
400         /* this is quite a common operation, so we want it to be
401            fast. We optimise for the ascii case, knowing that all our
402            supported multi-byte character sets are ascii-compatible
403            (ie. they match for the first 128 chars) */
404
405         for (p = s; *p; p++) {
406                 if (*p & 0x80) /* mb string - slow path. */
407                         break;
408                 if (*p == oldc)
409                         *p = newc;
410         }
411
412         if (!*p)
413                 return;
414
415         /* Slow (mb) path. */
416 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
417         /* With compose characters we must restart from the beginning. JRA. */
418         p = s;
419 #endif
420         push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE);
421         string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
422         pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
423 }
424
425 /**
426  Skip past some strings in a buffer.
427 **/
428
429 char *skip_string(char *buf,size_t n)
430 {
431         while (n--)
432                 buf += strlen(buf) + 1;
433         return(buf);
434 }
435
436 /**
437  Count the number of characters in a string. Normally this will
438  be the same as the number of bytes in a string for single byte strings,
439  but will be different for multibyte.
440 **/
441
442 size_t str_charnum(const char *s)
443 {
444         uint16 tmpbuf2[sizeof(pstring)];
445         push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
446         return strlen_w(tmpbuf2);
447 }
448
449 /**
450  Count the number of characters in a string. Normally this will
451  be the same as the number of bytes in a string for single byte strings,
452  but will be different for multibyte.
453 **/
454
455 size_t str_ascii_charnum(const char *s)
456 {
457         pstring tmpbuf2;
458         push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
459         return strlen(tmpbuf2);
460 }
461
462 BOOL trim_char(char *s,char cfront,char cback)
463 {
464         BOOL ret = False;
465         char *ep;
466         char *fp = s;
467
468         /* Ignore null or empty strings. */
469         if (!s || (s[0] == '\0'))
470                 return False;
471
472         if (cfront) {
473                 while (*fp && *fp == cfront)
474                         fp++;
475                 if (!*fp) {
476                         /* We ate the string. */
477                         s[0] = '\0';
478                         return True;
479                 }
480                 if (fp != s)
481                         ret = True;
482         }
483
484         ep = fp + strlen(fp) - 1;
485         if (cback) {
486                 /* Attempt ascii only. Bail for mb strings. */
487                 while ((ep >= fp) && (*ep == cback)) {
488                         ret = True;
489                         if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
490                                 /* Could be mb... bail back to tim_string. */
491                                 char fs[2], bs[2];
492                                 if (cfront) {
493                                         fs[0] = cfront;
494                                         fs[1] = '\0';
495                                 }
496                                 bs[0] = cback;
497                                 bs[1] = '\0';
498                                 return trim_string(s, cfront ? fs : NULL, bs);
499                         } else {
500                                 ep--;
501                         }
502                 }
503                 if (ep < fp) {
504                         /* We ate the string. */
505                         s[0] = '\0';
506                         return True;
507                 }
508         }
509
510         ep[1] = '\0';
511         memmove(s, fp, ep-fp+2);
512         return ret;
513 }
514
515 /**
516  Trim the specified elements off the front and back of a string.
517 **/
518
519 BOOL trim_string(char *s,const char *front,const char *back)
520 {
521         BOOL ret = False;
522         size_t front_len;
523         size_t back_len;
524         size_t len;
525
526         /* Ignore null or empty strings. */
527         if (!s || (s[0] == '\0'))
528                 return False;
529
530         front_len       = front? strlen(front) : 0;
531         back_len        = back? strlen(back) : 0;
532
533         len = strlen(s);
534
535         if (front_len) {
536                 while (len && strncmp(s, front, front_len)==0) {
537                         /* Must use memmove here as src & dest can
538                          * easily overlap. Found by valgrind. JRA. */
539                         memmove(s, s+front_len, (len-front_len)+1);
540                         len -= front_len;
541                         ret=True;
542                 }
543         }
544         
545         if (back_len) {
546                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
547                         s[len-back_len]='\0';
548                         len -= back_len;
549                         ret=True;
550                 }
551         }
552         return ret;
553 }
554
555 /**
556  Does a string have any uppercase chars in it?
557 **/
558
559 BOOL strhasupper(const char *s)
560 {
561         smb_ucs2_t *ptr;
562         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
563         for(ptr=tmpbuf;*ptr;ptr++)
564                 if(isupper_w(*ptr))
565                         return True;
566         return(False);
567 }
568
569 /**
570  Does a string have any lowercase chars in it?
571 **/
572
573 BOOL strhaslower(const char *s)
574 {
575         smb_ucs2_t *ptr;
576         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
577         for(ptr=tmpbuf;*ptr;ptr++)
578                 if(islower_w(*ptr))
579                         return True;
580         return(False);
581 }
582
583 /**
584  Find the number of 'c' chars in a string
585 **/
586
587 size_t count_chars(const char *s,char c)
588 {
589         smb_ucs2_t *ptr;
590         int count;
591         smb_ucs2_t *alloc_tmpbuf = NULL;
592
593         if (push_ucs2_allocate(&alloc_tmpbuf, s) == (size_t)-1) {
594                 return 0;
595         }
596
597         for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++)
598                 if(*ptr==UCS2_CHAR(c))
599                         count++;
600
601         SAFE_FREE(alloc_tmpbuf);
602         return(count);
603 }
604
605 /**
606  Safe string copy into a known length string. maxlength does not
607  include the terminating zero.
608 **/
609
610 char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_t maxlength)
611 {
612         size_t len;
613
614         if (!dest) {
615                 DEBUG(0,("ERROR: NULL dest in safe_strcpy, called from [%s][%d]\n", fn, line));
616                 return NULL;
617         }
618
619 #ifdef DEVELOPER
620         clobber_region(fn,line,dest, maxlength+1);
621 #endif
622
623         if (!src) {
624                 *dest = 0;
625                 return dest;
626         }  
627
628         len = strnlen(src, maxlength+1);
629
630         if (len > maxlength) {
631                 DEBUG(0,("ERROR: string overflow by %lu (%lu - %lu) in safe_strcpy [%.50s]\n",
632                          (unsigned long)(len-maxlength), (unsigned long)len, 
633                          (unsigned long)maxlength, src));
634                 len = maxlength;
635         }
636       
637         memmove(dest, src, len);
638         dest[len] = 0;
639         return dest;
640 }  
641
642 /**
643  Safe string cat into a string. maxlength does not
644  include the terminating zero.
645 **/
646 char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
647 {
648         size_t src_len, dest_len;
649
650         if (!dest) {
651                 DEBUG(0,("ERROR: NULL dest in safe_strcat, called from [%s][%d]\n", fn, line));
652                 return NULL;
653         }
654
655         if (!src)
656                 return dest;
657         
658         src_len = strnlen(src, maxlength + 1);
659         dest_len = strnlen(dest, maxlength + 1);
660
661 #ifdef DEVELOPER
662         clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
663 #endif
664
665         if (src_len + dest_len > maxlength) {
666                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
667                          (int)(src_len + dest_len - maxlength), src));
668                 if (maxlength > dest_len) {
669                         memcpy(&dest[dest_len], src, maxlength - dest_len);
670                 }
671                 dest[maxlength] = 0;
672                 return NULL;
673         }
674
675         memcpy(&dest[dest_len], src, src_len);
676         dest[dest_len + src_len] = 0;
677         return dest;
678 }
679
680 /**
681  Paranoid strcpy into a buffer of given length (includes terminating
682  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
683  and replaces with '_'. Deliberately does *NOT* check for multibyte
684  characters. Don't change it !
685 **/
686 char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
687 {
688         size_t len, i;
689
690 #ifdef DEVELOPER
691         clobber_region(fn, line, dest, maxlength);
692 #endif
693
694         if (!dest) {
695                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy, called from [%s][%d]\n", fn, line));
696                 return NULL;
697         }
698
699         if (!src) {
700                 *dest = 0;
701                 return dest;
702         }  
703
704         len = strlen(src);
705         if (len >= maxlength)
706                 len = maxlength - 1;
707
708         if (!other_safe_chars)
709                 other_safe_chars = "";
710
711         for(i = 0; i < len; i++) {
712                 int val = (src[i] & 0xff);
713                 if (isupper_ascii(val) || islower_ascii(val) || isdigit(val) || strchr_m(other_safe_chars, val))
714                         dest[i] = src[i];
715                 else
716                         dest[i] = '_';
717         }
718
719         dest[i] = '\0';
720
721         return dest;
722 }
723
724 /**
725  Like strncpy but always null terminates. Make sure there is room!
726  The variable n should always be one less than the available size.
727 **/
728 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
729 {
730         char *d = dest;
731
732 #ifdef DEVELOPER
733         clobber_region(fn, line, dest, n+1);
734 #endif
735
736         if (!dest) {
737                 DEBUG(0,("ERROR: NULL dest in StrnCpy, called from [%s][%d]\n", fn, line));
738                 return(NULL);
739         }
740
741         if (!src) {
742                 *dest = 0;
743                 return(dest);
744         }
745         
746         while (n-- && (*d = *src)) {
747                 d++;
748                 src++;
749         }
750
751         *d = 0;
752         return(dest);
753 }
754
755 #if 0
756 /**
757  Like strncpy but copies up to the character marker.  always null terminates.
758  returns a pointer to the character marker in the source string (src).
759 **/
760
761 static char *strncpyn(char *dest, const char *src, size_t n, char c)
762 {
763         char *p;
764         size_t str_len;
765
766 #ifdef DEVELOPER
767         clobber_region(dest, n+1);
768 #endif
769         p = strchr_m(src, c);
770         if (p == NULL) {
771                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
772                 return NULL;
773         }
774
775         str_len = PTR_DIFF(p, src);
776         strncpy(dest, src, MIN(n, str_len));
777         dest[str_len] = '\0';
778
779         return p;
780 }
781 #endif
782
783 /**
784  Routine to get hex characters and turn them into a 16 byte array.
785  the array can be variable length, and any non-hex-numeric
786  characters are skipped.  "0xnn" or "0Xnn" is specially catered
787  for.
788
789  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
790
791 **/
792
793 size_t strhex_to_str(char *p, size_t len, const char *strhex)
794 {
795         size_t i;
796         size_t num_chars = 0;
797         unsigned char   lonybble, hinybble;
798         const char     *hexchars = "0123456789ABCDEF";
799         char           *p1 = NULL, *p2 = NULL;
800
801         for (i = 0; i < len && strhex[i] != 0; i++) {
802                 if (strnequal(hexchars, "0x", 2)) {
803                         i++; /* skip two chars */
804                         continue;
805                 }
806
807                 if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
808                         break;
809
810                 i++; /* next hex digit */
811
812                 if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
813                         break;
814
815                 /* get the two nybbles */
816                 hinybble = PTR_DIFF(p1, hexchars);
817                 lonybble = PTR_DIFF(p2, hexchars);
818
819                 p[num_chars] = (hinybble << 4) | lonybble;
820                 num_chars++;
821
822                 p1 = NULL;
823                 p2 = NULL;
824         }
825         return num_chars;
826 }
827
828 DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex) 
829 {
830         DATA_BLOB ret_blob;
831
832         if (mem_ctx != NULL)
833                 ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
834         else
835                 ret_blob = data_blob(NULL, strlen(strhex)/2+1);
836
837         ret_blob.length = strhex_to_str((char*)ret_blob.data,   
838                                         strlen(strhex), 
839                                         strhex);
840
841         return ret_blob;
842 }
843
844 /**
845  * Routine to print a buffer as HEX digits, into an allocated string.
846  */
847
848 char *hex_encode(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
849 {
850         int i;
851         char *hex_buffer;
852
853         hex_buffer = TALLOC_ARRAY(mem_ctx, char, (len*2)+1);
854
855         for (i = 0; i < len; i++)
856                 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
857
858         return hex_buffer;
859 }
860
861 /**
862  Check if a string is part of a list.
863 **/
864
865 BOOL in_list(const char *s, const char *list, BOOL casesensitive)
866 {
867         pstring tok;
868         const char *p=list;
869
870         if (!list)
871                 return(False);
872
873         while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
874                 if (casesensitive) {
875                         if (strcmp(tok,s) == 0)
876                                 return(True);
877                 } else {
878                         if (StrCaseCmp(tok,s) == 0)
879                                 return(True);
880                 }
881         }
882         return(False);
883 }
884
885 /* this is used to prevent lots of mallocs of size 1 */
886 static const char *null_string = "";
887
888 /**
889  Set a string value, allocing the space for the string
890 **/
891
892 static BOOL string_init(char **dest,const char *src)
893 {
894         size_t l;
895
896         if (!src)     
897                 src = "";
898
899         l = strlen(src);
900
901         if (l == 0) {
902                 *dest = CONST_DISCARD(char*, null_string);
903         } else {
904                 (*dest) = SMB_STRDUP(src);
905                 if ((*dest) == NULL) {
906                         DEBUG(0,("Out of memory in string_init\n"));
907                         return False;
908                 }
909         }
910         return(True);
911 }
912
913 /**
914  Free a string value.
915 **/
916
917 void string_free(char **s)
918 {
919         if (!s || !(*s))
920                 return;
921         if (*s == null_string)
922                 *s = NULL;
923         SAFE_FREE(*s);
924 }
925
926 /**
927  Set a string value, deallocating any existing space, and allocing the space
928  for the string
929 **/
930
931 BOOL string_set(char **dest,const char *src)
932 {
933         string_free(dest);
934         return(string_init(dest,src));
935 }
936
937 /**
938  Substitute a string for a pattern in another string. Make sure there is 
939  enough room!
940
941  This routine looks for pattern in s and replaces it with 
942  insert. It may do multiple replacements or just one.
943
944  Any of " ; ' $ or ` in the insert string are replaced with _
945  if len==0 then the string cannot be extended. This is different from the old
946  use of len==0 which was for no length checks to be done.
947 **/
948
949 void string_sub2(char *s,const char *pattern, const char *insert, size_t len, 
950                  BOOL remove_unsafe_characters, BOOL replace_once, BOOL allow_trailing_dollar)
951 {
952         char *p;
953         ssize_t ls,lp,li, i;
954
955         if (!insert || !pattern || !*pattern || !s)
956                 return;
957
958         ls = (ssize_t)strlen(s);
959         lp = (ssize_t)strlen(pattern);
960         li = (ssize_t)strlen(insert);
961
962         if (len == 0)
963                 len = ls + 1; /* len is number of *bytes* */
964
965         while (lp <= ls && (p = strstr_m(s,pattern))) {
966                 if (ls + (li-lp) >= len) {
967                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
968                                  (int)(ls + (li-lp) - len),
969                                  pattern, (int)len));
970                         break;
971                 }
972                 if (li != lp) {
973                         memmove(p+li,p+lp,strlen(p+lp)+1);
974                 }
975                 for (i=0;i<li;i++) {
976                         switch (insert[i]) {
977                         case '`':
978                         case '"':
979                         case '\'':
980                         case ';':
981                         case '$':
982                                 /* allow a trailing $ (as in machine accounts) */
983                                 if (allow_trailing_dollar && (i == li - 1 )) {
984                                         p[i] = insert[i];
985                                         break;
986                                 }
987                         case '%':
988                         case '\r':
989                         case '\n':
990                                 if ( remove_unsafe_characters ) {
991                                         p[i] = '_';
992                                         /* yes this break should be here since we want to 
993                                            fall throw if not replacing unsafe chars */
994                                         break;
995                                 }
996                         default:
997                                 p[i] = insert[i];
998                         }
999                 }
1000                 s = p + li;
1001                 ls += (li-lp);
1002
1003                 if (replace_once)
1004                         break;
1005         }
1006 }
1007
1008 void string_sub_once(char *s, const char *pattern, const char *insert, size_t len)
1009 {
1010         string_sub2( s, pattern, insert, len, True, True, False );
1011 }
1012
1013 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
1014 {
1015         string_sub2( s, pattern, insert, len, True, False, False );
1016 }
1017
1018 void fstring_sub(char *s,const char *pattern,const char *insert)
1019 {
1020         string_sub(s, pattern, insert, sizeof(fstring));
1021 }
1022
1023 void pstring_sub(char *s,const char *pattern,const char *insert)
1024 {
1025         string_sub(s, pattern, insert, sizeof(pstring));
1026 }
1027
1028 /**
1029  Similar to string_sub, but it will accept only allocated strings
1030  and may realloc them so pay attention at what you pass on no
1031  pointers inside strings, no pstrings or const may be passed
1032  as string.
1033 **/
1034
1035 char *realloc_string_sub(char *string, const char *pattern,
1036                          const char *insert)
1037 {
1038         char *p, *in;
1039         char *s;
1040         ssize_t ls,lp,li,ld, i;
1041
1042         if (!insert || !pattern || !*pattern || !string || !*string)
1043                 return NULL;
1044
1045         s = string;
1046
1047         in = SMB_STRDUP(insert);
1048         if (!in) {
1049                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1050                 return NULL;
1051         }
1052         ls = (ssize_t)strlen(s);
1053         lp = (ssize_t)strlen(pattern);
1054         li = (ssize_t)strlen(insert);
1055         ld = li - lp;
1056         for (i=0;i<li;i++) {
1057                 switch (in[i]) {
1058                         case '`':
1059                         case '"':
1060                         case '\'':
1061                         case ';':
1062                         case '$':
1063                         case '%':
1064                         case '\r':
1065                         case '\n':
1066                                 in[i] = '_';
1067                         default:
1068                                 /* ok */
1069                                 break;
1070                 }
1071         }
1072         
1073         while ((p = strstr_m(s,pattern))) {
1074                 if (ld > 0) {
1075                         int offset = PTR_DIFF(s,string);
1076                         string = SMB_REALLOC(string, ls + ld + 1);
1077                         if (!string) {
1078                                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1079                                 SAFE_FREE(in);
1080                                 return NULL;
1081                         }
1082                         p = string + offset + (p - s);
1083                 }
1084                 if (li != lp) {
1085                         memmove(p+li,p+lp,strlen(p+lp)+1);
1086                 }
1087                 memcpy(p, in, li);
1088                 s = p + li;
1089                 ls += ld;
1090         }
1091         SAFE_FREE(in);
1092         return string;
1093 }
1094
1095 /* Same as string_sub, but returns a talloc'ed string */
1096
1097 char *talloc_string_sub(TALLOC_CTX *mem_ctx, const char *src,
1098                         const char *pattern, const char *insert)
1099 {
1100         char *p, *in;
1101         char *s;
1102         char *string;
1103         ssize_t ls,lp,li,ld, i;
1104
1105         if (!insert || !pattern || !*pattern || !src || !*src)
1106                 return NULL;
1107
1108         string = talloc_strdup(mem_ctx, src);
1109         if (string == NULL) {
1110                 DEBUG(0, ("talloc_strdup failed\n"));
1111                 return NULL;
1112         }
1113
1114         s = string;
1115
1116         in = SMB_STRDUP(insert);
1117         if (!in) {
1118                 DEBUG(0, ("talloc_string_sub: out of memory!\n"));
1119                 return NULL;
1120         }
1121         ls = (ssize_t)strlen(s);
1122         lp = (ssize_t)strlen(pattern);
1123         li = (ssize_t)strlen(insert);
1124         ld = li - lp;
1125         for (i=0;i<li;i++) {
1126                 switch (in[i]) {
1127                         case '`':
1128                         case '"':
1129                         case '\'':
1130                         case ';':
1131                         case '$':
1132                         case '%':
1133                         case '\r':
1134                         case '\n':
1135                                 in[i] = '_';
1136                         default:
1137                                 /* ok */
1138                                 break;
1139                 }
1140         }
1141         
1142         while ((p = strstr_m(s,pattern))) {
1143                 if (ld > 0) {
1144                         int offset = PTR_DIFF(s,string);
1145                         string = TALLOC_REALLOC(mem_ctx, string, ls + ld + 1);
1146                         if (!string) {
1147                                 DEBUG(0, ("talloc_string_sub: out of "
1148                                           "memory!\n"));
1149                                 SAFE_FREE(in);
1150                                 return NULL;
1151                         }
1152                         p = string + offset + (p - s);
1153                 }
1154                 if (li != lp) {
1155                         memmove(p+li,p+lp,strlen(p+lp)+1);
1156                 }
1157                 memcpy(p, in, li);
1158                 s = p + li;
1159                 ls += ld;
1160         }
1161         SAFE_FREE(in);
1162         return string;
1163 }
1164
1165 /**
1166  Similar to string_sub() but allows for any character to be substituted. 
1167  Use with caution!
1168  if len==0 then the string cannot be extended. This is different from the old
1169  use of len==0 which was for no length checks to be done.
1170 **/
1171
1172 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1173 {
1174         char *p;
1175         ssize_t ls,lp,li;
1176
1177         if (!insert || !pattern || !s)
1178                 return;
1179
1180         ls = (ssize_t)strlen(s);
1181         lp = (ssize_t)strlen(pattern);
1182         li = (ssize_t)strlen(insert);
1183
1184         if (!*pattern)
1185                 return;
1186         
1187         if (len == 0)
1188                 len = ls + 1; /* len is number of *bytes* */
1189         
1190         while (lp <= ls && (p = strstr_m(s,pattern))) {
1191                 if (ls + (li-lp) >= len) {
1192                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
1193                                  (int)(ls + (li-lp) - len),
1194                                  pattern, (int)len));
1195                         break;
1196                 }
1197                 if (li != lp) {
1198                         memmove(p+li,p+lp,strlen(p+lp)+1);
1199                 }
1200                 memcpy(p, insert, li);
1201                 s = p + li;
1202                 ls += (li-lp);
1203         }
1204 }
1205
1206 /**
1207  Similar to all_string_sub but for unicode strings.
1208  Return a new allocated unicode string.
1209  similar to string_sub() but allows for any character to be substituted.
1210  Use with caution!
1211 **/
1212
1213 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
1214                                 const smb_ucs2_t *insert)
1215 {
1216         smb_ucs2_t *r, *rp;
1217         const smb_ucs2_t *sp;
1218         size_t  lr, lp, li, lt;
1219
1220         if (!insert || !pattern || !*pattern || !s)
1221                 return NULL;
1222
1223         lt = (size_t)strlen_w(s);
1224         lp = (size_t)strlen_w(pattern);
1225         li = (size_t)strlen_w(insert);
1226
1227         if (li > lp) {
1228                 const smb_ucs2_t *st = s;
1229                 int ld = li - lp;
1230                 while ((sp = strstr_w(st, pattern))) {
1231                         st = sp + lp;
1232                         lt += ld;
1233                 }
1234         }
1235
1236         r = rp = SMB_MALLOC_ARRAY(smb_ucs2_t, lt + 1);
1237         if (!r) {
1238                 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
1239                 return NULL;
1240         }
1241
1242         while ((sp = strstr_w(s, pattern))) {
1243                 memcpy(rp, s, (sp - s));
1244                 rp += ((sp - s) / sizeof(smb_ucs2_t));
1245                 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
1246                 s = sp + lp;
1247                 rp += li;
1248         }
1249         lr = ((rp - r) / sizeof(smb_ucs2_t));
1250         if (lr < lt) {
1251                 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
1252                 rp += (lt - lr);
1253         }
1254         *rp = 0;
1255
1256         return r;
1257 }
1258
1259 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
1260                                              const char *insert)
1261 {
1262         wpstring p, i;
1263
1264         if (!insert || !pattern || !s)
1265                 return NULL;
1266         push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1267         push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1268         return all_string_sub_w(s, p, i);
1269 }
1270
1271 #if 0
1272 /**
1273  Splits out the front and back at a separator.
1274 **/
1275
1276 static void split_at_last_component(char *path, char *front, char sep, char *back)
1277 {
1278         char *p = strrchr_m(path, sep);
1279
1280         if (p != NULL)
1281                 *p = 0;
1282
1283         if (front != NULL)
1284                 pstrcpy(front, path);
1285
1286         if (p != NULL) {
1287                 if (back != NULL)
1288                         pstrcpy(back, p+1);
1289                 *p = '\\';
1290         } else {
1291                 if (back != NULL)
1292                         back[0] = 0;
1293         }
1294 }
1295 #endif
1296
1297 /**
1298  Write an octal as a string.
1299 **/
1300
1301 const char *octal_string(int i)
1302 {
1303         static char ret[64];
1304         if (i == -1)
1305                 return "-1";
1306         slprintf(ret, sizeof(ret)-1, "0%o", i);
1307         return ret;
1308 }
1309
1310
1311 /**
1312  Truncate a string at a specified length.
1313 **/
1314
1315 char *string_truncate(char *s, unsigned int length)
1316 {
1317         if (s && strlen(s) > length)
1318                 s[length] = 0;
1319         return s;
1320 }
1321
1322 /**
1323  Strchr and strrchr_m are very hard to do on general multi-byte strings. 
1324  We convert via ucs2 for now.
1325 **/
1326
1327 char *strchr_m(const char *src, char c)
1328 {
1329         wpstring ws;
1330         pstring s2;
1331         smb_ucs2_t *p;
1332         const char *s;
1333
1334         /* characters below 0x3F are guaranteed to not appear in
1335            non-initial position in multi-byte charsets */
1336         if ((c & 0xC0) == 0) {
1337                 return strchr(src, c);
1338         }
1339
1340         /* this is quite a common operation, so we want it to be
1341            fast. We optimise for the ascii case, knowing that all our
1342            supported multi-byte character sets are ascii-compatible
1343            (ie. they match for the first 128 chars) */
1344
1345         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1346                 if (*s == c)
1347                         return (char *)s;
1348         }
1349
1350         if (!*s)
1351                 return NULL;
1352
1353 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1354         /* With compose characters we must restart from the beginning. JRA. */
1355         s = src;
1356 #endif
1357
1358         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1359         p = strchr_w(ws, UCS2_CHAR(c));
1360         if (!p)
1361                 return NULL;
1362         *p = 0;
1363         pull_ucs2_pstring(s2, ws);
1364         return (char *)(s+strlen(s2));
1365 }
1366
1367 char *strrchr_m(const char *s, char c)
1368 {
1369         /* characters below 0x3F are guaranteed to not appear in
1370            non-initial position in multi-byte charsets */
1371         if ((c & 0xC0) == 0) {
1372                 return strrchr(s, c);
1373         }
1374
1375         /* this is quite a common operation, so we want it to be
1376            fast. We optimise for the ascii case, knowing that all our
1377            supported multi-byte character sets are ascii-compatible
1378            (ie. they match for the first 128 chars). Also, in Samba
1379            we only search for ascii characters in 'c' and that
1380            in all mb character sets with a compound character
1381            containing c, if 'c' is not a match at position
1382            p, then p[-1] > 0x7f. JRA. */
1383
1384         {
1385                 size_t len = strlen(s);
1386                 const char *cp = s;
1387                 BOOL got_mb = False;
1388
1389                 if (len == 0)
1390                         return NULL;
1391                 cp += (len - 1);
1392                 do {
1393                         if (c == *cp) {
1394                                 /* Could be a match. Part of a multibyte ? */
1395                                 if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
1396                                         /* Yep - go slow :-( */
1397                                         got_mb = True;
1398                                         break;
1399                                 }
1400                                 /* No - we have a match ! */
1401                                 return (char *)cp;
1402                         }
1403                 } while (cp-- != s);
1404                 if (!got_mb)
1405                         return NULL;
1406         }
1407
1408         /* String contained a non-ascii char. Slow path. */
1409         {
1410                 wpstring ws;
1411                 pstring s2;
1412                 smb_ucs2_t *p;
1413
1414                 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1415                 p = strrchr_w(ws, UCS2_CHAR(c));
1416                 if (!p)
1417                         return NULL;
1418                 *p = 0;
1419                 pull_ucs2_pstring(s2, ws);
1420                 return (char *)(s+strlen(s2));
1421         }
1422 }
1423
1424 /***********************************************************************
1425  Return the equivalent of doing strrchr 'n' times - always going
1426  backwards.
1427 ***********************************************************************/
1428
1429 char *strnrchr_m(const char *s, char c, unsigned int n)
1430 {
1431         wpstring ws;
1432         pstring s2;
1433         smb_ucs2_t *p;
1434
1435         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1436         p = strnrchr_w(ws, UCS2_CHAR(c), n);
1437         if (!p)
1438                 return NULL;
1439         *p = 0;
1440         pull_ucs2_pstring(s2, ws);
1441         return (char *)(s+strlen(s2));
1442 }
1443
1444 /***********************************************************************
1445  strstr_m - We convert via ucs2 for now.
1446 ***********************************************************************/
1447
1448 char *strstr_m(const char *src, const char *findstr)
1449 {
1450         smb_ucs2_t *p;
1451         smb_ucs2_t *src_w, *find_w;
1452         const char *s;
1453         char *s2;
1454         char *retp;
1455
1456         size_t findstr_len = 0;
1457
1458         /* for correctness */
1459         if (!findstr[0]) {
1460                 return (char*)src;
1461         }
1462
1463         /* Samba does single character findstr calls a *lot*. */
1464         if (findstr[1] == '\0')
1465                 return strchr_m(src, *findstr);
1466
1467         /* We optimise for the ascii case, knowing that all our
1468            supported multi-byte character sets are ascii-compatible
1469            (ie. they match for the first 128 chars) */
1470
1471         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1472                 if (*s == *findstr) {
1473                         if (!findstr_len) 
1474                                 findstr_len = strlen(findstr);
1475
1476                         if (strncmp(s, findstr, findstr_len) == 0) {
1477                                 return (char *)s;
1478                         }
1479                 }
1480         }
1481
1482         if (!*s)
1483                 return NULL;
1484
1485 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
1486         /* 'make check' fails unless we do this */
1487
1488         /* With compose characters we must restart from the beginning. JRA. */
1489         s = src;
1490 #endif
1491
1492         if (push_ucs2_allocate(&src_w, src) == (size_t)-1) {
1493                 DEBUG(0,("strstr_m: src malloc fail\n"));
1494                 return NULL;
1495         }
1496         
1497         if (push_ucs2_allocate(&find_w, findstr) == (size_t)-1) {
1498                 SAFE_FREE(src_w);
1499                 DEBUG(0,("strstr_m: find malloc fail\n"));
1500                 return NULL;
1501         }
1502
1503         p = strstr_w(src_w, find_w);
1504
1505         if (!p) {
1506                 SAFE_FREE(src_w);
1507                 SAFE_FREE(find_w);
1508                 return NULL;
1509         }
1510         
1511         *p = 0;
1512         if (pull_ucs2_allocate(&s2, src_w) == (size_t)-1) {
1513                 SAFE_FREE(src_w);
1514                 SAFE_FREE(find_w);
1515                 DEBUG(0,("strstr_m: dest malloc fail\n"));
1516                 return NULL;
1517         }
1518         retp = (char *)(s+strlen(s2));
1519         SAFE_FREE(src_w);
1520         SAFE_FREE(find_w);
1521         SAFE_FREE(s2);
1522         return retp;
1523 }
1524
1525 /**
1526  Convert a string to lower case.
1527 **/
1528
1529 void strlower_m(char *s)
1530 {
1531         size_t len;
1532         int errno_save;
1533
1534         /* this is quite a common operation, so we want it to be
1535            fast. We optimise for the ascii case, knowing that all our
1536            supported multi-byte character sets are ascii-compatible
1537            (ie. they match for the first 128 chars) */
1538
1539         while (*s && !(((unsigned char)s[0]) & 0x80)) {
1540                 *s = tolower_ascii((unsigned char)*s);
1541                 s++;
1542         }
1543
1544         if (!*s)
1545                 return;
1546
1547         /* I assume that lowercased string takes the same number of bytes
1548          * as source string even in UTF-8 encoding. (VIV) */
1549         len = strlen(s) + 1;
1550         errno_save = errno;
1551         errno = 0;
1552         unix_strlower(s,len,s,len);     
1553         /* Catch mb conversion errors that may not terminate. */
1554         if (errno)
1555                 s[len-1] = '\0';
1556         errno = errno_save;
1557 }
1558
1559 /**
1560  Convert a string to upper case.
1561 **/
1562
1563 void strupper_m(char *s)
1564 {
1565         size_t len;
1566         int errno_save;
1567
1568         /* this is quite a common operation, so we want it to be
1569            fast. We optimise for the ascii case, knowing that all our
1570            supported multi-byte character sets are ascii-compatible
1571            (ie. they match for the first 128 chars) */
1572
1573         while (*s && !(((unsigned char)s[0]) & 0x80)) {
1574                 *s = toupper_ascii((unsigned char)*s);
1575                 s++;
1576         }
1577
1578         if (!*s)
1579                 return;
1580
1581         /* I assume that lowercased string takes the same number of bytes
1582          * as source string even in multibyte encoding. (VIV) */
1583         len = strlen(s) + 1;
1584         errno_save = errno;
1585         errno = 0;
1586         unix_strupper(s,len,s,len);     
1587         /* Catch mb conversion errors that may not terminate. */
1588         if (errno)
1589                 s[len-1] = '\0';
1590         errno = errno_save;
1591 }
1592
1593 /**
1594  Return a RFC2254 binary string representation of a buffer.
1595  Used in LDAP filters.
1596  Caller must free.
1597 **/
1598
1599 char *binary_string_rfc2254(char *buf, int len)
1600 {
1601         char *s;
1602         int i, j;
1603         const char *hex = "0123456789ABCDEF";
1604         s = SMB_MALLOC(len * 3 + 1);
1605         if (!s)
1606                 return NULL;
1607         for (j=i=0;i<len;i++) {
1608                 s[j] = '\\';
1609                 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1610                 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1611                 j += 3;
1612         }
1613         s[j] = 0;
1614         return s;
1615 }
1616
1617 char *binary_string(char *buf, int len)
1618 {
1619         char *s;
1620         int i, j;
1621         const char *hex = "0123456789ABCDEF";
1622         s = SMB_MALLOC(len * 2 + 1);
1623         if (!s)
1624                 return NULL;
1625         for (j=i=0;i<len;i++) {
1626                 s[j]   = hex[((unsigned char)buf[i]) >> 4];
1627                 s[j+1] = hex[((unsigned char)buf[i]) & 0xF];
1628                 j += 2;
1629         }
1630         s[j] = 0;
1631         return s;
1632 }
1633 /**
1634  Just a typesafety wrapper for snprintf into a pstring.
1635 **/
1636
1637  int pstr_sprintf(pstring s, const char *fmt, ...)
1638 {
1639         va_list ap;
1640         int ret;
1641
1642         va_start(ap, fmt);
1643         ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1644         va_end(ap);
1645         return ret;
1646 }
1647
1648
1649 /**
1650  Just a typesafety wrapper for snprintf into a fstring.
1651 **/
1652
1653 int fstr_sprintf(fstring s, const char *fmt, ...)
1654 {
1655         va_list ap;
1656         int ret;
1657
1658         va_start(ap, fmt);
1659         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1660         va_end(ap);
1661         return ret;
1662 }
1663
1664
1665 #if !defined(HAVE_STRNDUP) || defined(BROKEN_STRNDUP)
1666 /**
1667  Some platforms don't have strndup.
1668 **/
1669 #if defined(PARANOID_MALLOC_CHECKER)
1670 #undef strndup
1671 #endif
1672
1673  char *strndup(const char *s, size_t n)
1674 {
1675         char *ret;
1676         
1677         n = strnlen(s, n);
1678         ret = SMB_MALLOC(n+1);
1679         if (!ret)
1680                 return NULL;
1681         memcpy(ret, s, n);
1682         ret[n] = 0;
1683
1684         return ret;
1685 }
1686
1687 #if defined(PARANOID_MALLOC_CHECKER)
1688 #define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
1689 #endif
1690
1691 #endif
1692
1693 #if !defined(HAVE_STRNLEN) || defined(BROKEN_STRNLEN)
1694 /**
1695  Some platforms don't have strnlen
1696 **/
1697
1698  size_t strnlen(const char *s, size_t n)
1699 {
1700         size_t i;
1701         for (i=0; i<n && s[i] != '\0'; i++)
1702                 /* noop */ ;
1703         return i;
1704 }
1705 #endif
1706
1707 /**
1708  List of Strings manipulation functions
1709 **/
1710
1711 #define S_LIST_ABS 16 /* List Allocation Block Size */
1712
1713 static char **str_list_make_internal(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
1714 {
1715         char **list, **rlist;
1716         const char *str;
1717         char *s;
1718         int num, lsize;
1719         pstring tok;
1720         
1721         if (!string || !*string)
1722                 return NULL;
1723         if (mem_ctx) {
1724                 s = talloc_strdup(mem_ctx, string);
1725         } else {
1726                 s = SMB_STRDUP(string);
1727         }
1728         if (!s) {
1729                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1730                 return NULL;
1731         }
1732         if (!sep) sep = LIST_SEP;
1733         
1734         num = lsize = 0;
1735         list = NULL;
1736         
1737         str = s;
1738         while (next_token(&str, tok, sep, sizeof(tok))) {               
1739                 if (num == lsize) {
1740                         lsize += S_LIST_ABS;
1741                         if (mem_ctx) {
1742                                 rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *, lsize +1);
1743                         } else {
1744                                 /* We need to keep the old list on error so we can free the elements
1745                                    if the realloc fails. */
1746                                 rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, char *, lsize +1);
1747                         }
1748                         if (!rlist) {
1749                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1750                                 str_list_free(&list);
1751                                 if (mem_ctx) {
1752                                         TALLOC_FREE(s);
1753                                 } else {
1754                                         SAFE_FREE(s);
1755                                 }
1756                                 return NULL;
1757                         } else {
1758                                 list = rlist;
1759                         }
1760                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1761                 }
1762
1763                 if (mem_ctx) {
1764                         list[num] = talloc_strdup(mem_ctx, tok);
1765                 } else {
1766                         list[num] = SMB_STRDUP(tok);
1767                 }
1768                 
1769                 if (!list[num]) {
1770                         DEBUG(0,("str_list_make: Unable to allocate memory"));
1771                         str_list_free(&list);
1772                         if (mem_ctx) {
1773                                 TALLOC_FREE(s);
1774                         } else {
1775                                 SAFE_FREE(s);
1776                         }
1777                         return NULL;
1778                 }
1779         
1780                 num++;  
1781         }
1782
1783         if (mem_ctx) {
1784                 TALLOC_FREE(s);
1785         } else {
1786                 SAFE_FREE(s);
1787         }
1788
1789         return list;
1790 }
1791
1792 char **str_list_make_talloc(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
1793 {
1794         return str_list_make_internal(mem_ctx, string, sep);
1795 }
1796
1797 char **str_list_make(const char *string, const char *sep)
1798 {
1799         return str_list_make_internal(NULL, string, sep);
1800 }
1801
1802 BOOL str_list_copy(char ***dest, const char **src)
1803 {
1804         char **list, **rlist;
1805         int num, lsize;
1806         
1807         *dest = NULL;
1808         if (!src)
1809                 return False;
1810         
1811         num = lsize = 0;
1812         list = NULL;
1813                 
1814         while (src[num]) {
1815                 if (num == lsize) {
1816                         lsize += S_LIST_ABS;
1817                         rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, char *, lsize +1);
1818                         if (!rlist) {
1819                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1820                                 str_list_free(&list);
1821                                 return False;
1822                         } else {
1823                                 list = rlist;
1824                         }
1825                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1826                 }
1827                 
1828                 list[num] = SMB_STRDUP(src[num]);
1829                 if (!list[num]) {
1830                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
1831                         str_list_free(&list);
1832                         return False;
1833                 }
1834
1835                 num++;
1836         }
1837         
1838         *dest = list;
1839         return True;    
1840 }
1841
1842 /**
1843  * Return true if all the elements of the list match exactly.
1844  **/
1845 BOOL str_list_compare(char **list1, char **list2)
1846 {
1847         int num;
1848         
1849         if (!list1 || !list2)
1850                 return (list1 == list2); 
1851         
1852         for (num = 0; list1[num]; num++) {
1853                 if (!list2[num])
1854                         return False;
1855                 if (!strcsequal(list1[num], list2[num]))
1856                         return False;
1857         }
1858         if (list2[num])
1859                 return False; /* if list2 has more elements than list1 fail */
1860         
1861         return True;
1862 }
1863
1864 static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list)
1865 {
1866         char **tlist;
1867         
1868         if (!list || !*list)
1869                 return;
1870         tlist = *list;
1871         for(; *tlist; tlist++) {
1872                 if (mem_ctx) {
1873                         TALLOC_FREE(*tlist);
1874                 } else {
1875                         SAFE_FREE(*tlist);
1876                 }
1877         }
1878         if (mem_ctx) {
1879                 TALLOC_FREE(*tlist);
1880         } else {
1881                 SAFE_FREE(*list);
1882         }
1883 }
1884
1885 void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list)
1886 {
1887         str_list_free_internal(mem_ctx, list);
1888 }
1889
1890 void str_list_free(char ***list)
1891 {
1892         str_list_free_internal(NULL, list);
1893 }
1894
1895 /******************************************************************************
1896  *****************************************************************************/
1897
1898 int str_list_count( const char **list )
1899 {
1900         int i = 0;
1901
1902         if ( ! list )
1903                 return 0;
1904
1905         /* count the number of list members */
1906         
1907         for ( i=0; *list; i++, list++ );
1908         
1909         return i;
1910 }
1911
1912 /******************************************************************************
1913  version of standard_sub_basic() for string lists; uses alloc_sub_basic() 
1914  for the work
1915  *****************************************************************************/
1916  
1917 BOOL str_list_sub_basic( char **list, const char *smb_name )
1918 {
1919         char *s, *tmpstr;
1920         
1921         while ( *list ) {
1922                 s = *list;
1923                 tmpstr = alloc_sub_basic(smb_name, s);
1924                 if ( !tmpstr ) {
1925                         DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
1926                         return False;
1927                 }
1928
1929                 SAFE_FREE(*list);
1930                 *list = tmpstr;
1931                         
1932                 list++;
1933         }
1934
1935         return True;
1936 }
1937
1938 /******************************************************************************
1939  substritute a specific pattern in a string list
1940  *****************************************************************************/
1941  
1942 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1943 {
1944         char *p, *s, *t;
1945         ssize_t ls, lp, li, ld, i, d;
1946
1947         if (!list)
1948                 return False;
1949         if (!pattern)
1950                 return False;
1951         if (!insert)
1952                 return False;
1953
1954         lp = (ssize_t)strlen(pattern);
1955         li = (ssize_t)strlen(insert);
1956         ld = li -lp;
1957                         
1958         while (*list) {
1959                 s = *list;
1960                 ls = (ssize_t)strlen(s);
1961
1962                 while ((p = strstr_m(s, pattern))) {
1963                         t = *list;
1964                         d = p -t;
1965                         if (ld) {
1966                                 t = (char *) SMB_MALLOC(ls +ld +1);
1967                                 if (!t) {
1968                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1969                                         return False;
1970                                 }
1971                                 memcpy(t, *list, d);
1972                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1973                                 SAFE_FREE(*list);
1974                                 *list = t;
1975                                 ls += ld;
1976                                 s = t +d +li;
1977                         }
1978                         
1979                         for (i = 0; i < li; i++) {
1980                                 switch (insert[i]) {
1981                                         case '`':
1982                                         case '"':
1983                                         case '\'':
1984                                         case ';':
1985                                         case '$':
1986                                         case '%':
1987                                         case '\r':
1988                                         case '\n':
1989                                                 t[d +i] = '_';
1990                                                 break;
1991                                         default:
1992                                                 t[d +i] = insert[i];
1993                                 }
1994                         }       
1995                 }
1996                 
1997                 
1998                 list++;
1999         }
2000         
2001         return True;
2002 }
2003
2004
2005 #define IPSTR_LIST_SEP  ","
2006 #define IPSTR_LIST_CHAR ','
2007
2008 /**
2009  * Add ip string representation to ipstr list. Used also
2010  * as part of @function ipstr_list_make
2011  *
2012  * @param ipstr_list pointer to string containing ip list;
2013  *        MUST BE already allocated and IS reallocated if necessary
2014  * @param ipstr_size pointer to current size of ipstr_list (might be changed
2015  *        as a result of reallocation)
2016  * @param ip IP address which is to be added to list
2017  * @return pointer to string appended with new ip and possibly
2018  *         reallocated to new length
2019  **/
2020
2021 char* ipstr_list_add(char** ipstr_list, const struct ip_service *service)
2022 {
2023         char* new_ipstr = NULL;
2024         
2025         /* arguments checking */
2026         if (!ipstr_list || !service) return NULL;
2027
2028         /* attempt to convert ip to a string and append colon separator to it */
2029         if (*ipstr_list) {
2030                 asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP,
2031                         inet_ntoa(service->ip), service->port);
2032                 SAFE_FREE(*ipstr_list);
2033         } else {
2034                 asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port);
2035         }
2036         *ipstr_list = new_ipstr;
2037         return *ipstr_list;
2038 }
2039
2040
2041 /**
2042  * Allocate and initialise an ipstr list using ip adresses
2043  * passed as arguments.
2044  *
2045  * @param ipstr_list pointer to string meant to be allocated and set
2046  * @param ip_list array of ip addresses to place in the list
2047  * @param ip_count number of addresses stored in ip_list
2048  * @return pointer to allocated ip string
2049  **/
2050  
2051 char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count)
2052 {
2053         int i;
2054         
2055         /* arguments checking */
2056         if (!ip_list && !ipstr_list) return 0;
2057
2058         *ipstr_list = NULL;
2059         
2060         /* process ip addresses given as arguments */
2061         for (i = 0; i < ip_count; i++)
2062                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
2063         
2064         return (*ipstr_list);
2065 }
2066
2067
2068 /**
2069  * Parse given ip string list into array of ip addresses
2070  * (as ip_service structures)  
2071  *    e.g. 192.168.1.100:389,192.168.1.78, ...
2072  *
2073  * @param ipstr ip string list to be parsed 
2074  * @param ip_list pointer to array of ip addresses which is
2075  *        allocated by this function and must be freed by caller
2076  * @return number of succesfully parsed addresses
2077  **/
2078  
2079 int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list)
2080 {
2081         fstring token_str;
2082         size_t count;
2083         int i;
2084
2085         if (!ipstr_list || !ip_list) 
2086                 return 0;
2087         
2088         count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
2089         if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
2090                 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count));
2091                 return 0;
2092         }
2093         
2094         for ( i=0; 
2095                 next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count; 
2096                 i++ ) 
2097         {
2098                 struct in_addr addr;
2099                 unsigned port = 0;      
2100                 char *p = strchr(token_str, ':');
2101                 
2102                 if (p) {
2103                         *p = 0;
2104                         port = atoi(p+1);
2105                 }
2106
2107                 /* convert single token to ip address */
2108                 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
2109                         break;
2110                                 
2111                 (*ip_list)[i].ip = addr;
2112                 (*ip_list)[i].port = port;
2113         }
2114         
2115         return count;
2116 }
2117
2118
2119 /**
2120  * Safely free ip string list
2121  *
2122  * @param ipstr_list ip string list to be freed
2123  **/
2124
2125 void ipstr_list_free(char* ipstr_list)
2126 {
2127         SAFE_FREE(ipstr_list);
2128 }
2129
2130
2131 /**
2132  Unescape a URL encoded string, in place.
2133 **/
2134
2135 void rfc1738_unescape(char *buf)
2136 {
2137         char *p=buf;
2138
2139         while (p && *p && (p=strchr_m(p,'%'))) {
2140                 int c1 = p[1];
2141                 int c2 = p[2];
2142
2143                 if (c1 >= '0' && c1 <= '9')
2144                         c1 = c1 - '0';
2145                 else if (c1 >= 'A' && c1 <= 'F')
2146                         c1 = 10 + c1 - 'A';
2147                 else if (c1 >= 'a' && c1 <= 'f')
2148                         c1 = 10 + c1 - 'a';
2149                 else {p++; continue;}
2150
2151                 if (c2 >= '0' && c2 <= '9')
2152                         c2 = c2 - '0';
2153                 else if (c2 >= 'A' && c2 <= 'F')
2154                         c2 = 10 + c2 - 'A';
2155                 else if (c2 >= 'a' && c2 <= 'f')
2156                         c2 = 10 + c2 - 'a';
2157                 else {p++; continue;}
2158                         
2159                 *p = (c1<<4) | c2;
2160
2161                 memmove(p+1, p+3, strlen(p+3)+1);
2162                 p++;
2163         }
2164 }
2165
2166 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2167
2168 /**
2169  * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
2170  **/
2171 DATA_BLOB base64_decode_data_blob(const char *s)
2172 {
2173         int bit_offset, byte_offset, idx, i, n;
2174         DATA_BLOB decoded = data_blob(s, strlen(s)+1);
2175         unsigned char *d = decoded.data;
2176         char *p;
2177
2178         n=i=0;
2179
2180         while (*s && (p=strchr_m(b64,*s))) {
2181                 idx = (int)(p - b64);
2182                 byte_offset = (i*6)/8;
2183                 bit_offset = (i*6)%8;
2184                 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
2185                 if (bit_offset < 3) {
2186                         d[byte_offset] |= (idx << (2-bit_offset));
2187                         n = byte_offset+1;
2188                 } else {
2189                         d[byte_offset] |= (idx >> (bit_offset-2));
2190                         d[byte_offset+1] = 0;
2191                         d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
2192                         n = byte_offset+2;
2193                 }
2194                 s++; i++;
2195         }
2196
2197         if ((n > 0) && (*s == '=')) {
2198                 n -= 1;
2199         }
2200
2201         /* fix up length */
2202         decoded.length = n;
2203         return decoded;
2204 }
2205
2206 /**
2207  * Decode a base64 string in-place - wrapper for the above
2208  **/
2209 void base64_decode_inplace(char *s)
2210 {
2211         DATA_BLOB decoded = base64_decode_data_blob(s);
2212
2213         if ( decoded.length != 0 ) {
2214                 memcpy(s, decoded.data, decoded.length);
2215
2216                 /* null terminate */
2217                 s[decoded.length] = '\0';
2218         } else {
2219                 *s = '\0';
2220         }
2221
2222         data_blob_free(&decoded);
2223 }
2224
2225 /**
2226  * Encode a base64 string into a malloc()ed string caller to free.
2227  *
2228  *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
2229  **/
2230 char * base64_encode_data_blob(DATA_BLOB data)
2231 {
2232         int bits = 0;
2233         int char_count = 0;
2234         size_t out_cnt, len, output_len;
2235         char *result;
2236
2237         if (!data.length || !data.data)
2238                 return NULL;
2239
2240         out_cnt = 0;
2241         len = data.length;
2242         output_len = data.length * 2;
2243         result = SMB_MALLOC(output_len); /* get us plenty of space */
2244
2245         while (len-- && out_cnt < (data.length * 2) - 5) {
2246                 int c = (unsigned char) *(data.data++);
2247                 bits += c;
2248                 char_count++;
2249                 if (char_count == 3) {
2250                         result[out_cnt++] = b64[bits >> 18];
2251                         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2252                         result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2253             result[out_cnt++] = b64[bits & 0x3f];
2254             bits = 0;
2255             char_count = 0;
2256         } else {
2257             bits <<= 8;
2258         }
2259     }
2260     if (char_count != 0) {
2261         bits <<= 16 - (8 * char_count);
2262         result[out_cnt++] = b64[bits >> 18];
2263         result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2264         if (char_count == 1) {
2265             result[out_cnt++] = '=';
2266             result[out_cnt++] = '=';
2267         } else {
2268             result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2269             result[out_cnt++] = '=';
2270         }
2271     }
2272     result[out_cnt] = '\0';     /* terminate */
2273     return result;
2274 }
2275
2276 /* read a SMB_BIG_UINT from a string */
2277 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
2278 {
2279
2280         SMB_BIG_UINT val = -1;
2281         const char *p = nptr;
2282         
2283         if (!p) {
2284                 *entptr = p;
2285                 return val;
2286         }
2287
2288         while (*p && isspace(*p))
2289                 p++;
2290
2291 #ifdef LARGE_SMB_OFF_T
2292         sscanf(p,"%llu",&val);  
2293 #else /* LARGE_SMB_OFF_T */
2294         sscanf(p,"%lu",&val);
2295 #endif /* LARGE_SMB_OFF_T */
2296         if (entptr) {
2297                 while (*p && isdigit(*p))
2298                         p++;
2299                 *entptr = p;
2300         }
2301
2302         return val;
2303 }
2304
2305 void string_append(char **left, const char *right)
2306 {
2307         int new_len = strlen(right) + 1;
2308
2309         if (*left == NULL) {
2310                 *left = SMB_MALLOC(new_len);
2311                 *left[0] = '\0';
2312         } else {
2313                 new_len += strlen(*left);
2314                 *left = SMB_REALLOC(*left, new_len);
2315         }
2316
2317         if (*left == NULL) {
2318                 return;
2319         }
2320
2321         safe_strcat(*left, right, new_len-1);
2322 }
2323
2324 BOOL add_string_to_array(TALLOC_CTX *mem_ctx,
2325                          const char *str, const char ***strings,
2326                          int *num)
2327 {
2328         char *dup_str = talloc_strdup(mem_ctx, str);
2329
2330         *strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings, const char *, (*num)+1);
2331
2332         if ((*strings == NULL) || (dup_str == NULL))
2333                 return False;
2334
2335         (*strings)[*num] = dup_str;
2336         *num += 1;
2337         return True;
2338 }
2339
2340 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
2341  * error checking in between. The indiation that something weird happened is
2342  * string==NULL */
2343
2344 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
2345                     size_t *bufsize, const char *fmt, ...)
2346 {
2347         va_list ap;
2348         char *newstr;
2349         int ret;
2350         BOOL increased;
2351
2352         /* len<0 is an internal marker that something failed */
2353         if (*len < 0)
2354                 goto error;
2355
2356         if (*string == NULL) {
2357                 if (*bufsize == 0)
2358                         *bufsize = 128;
2359
2360                 if (mem_ctx != NULL)
2361                         *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
2362                 else
2363                         *string = SMB_MALLOC_ARRAY(char, *bufsize);
2364
2365                 if (*string == NULL)
2366                         goto error;
2367         }
2368
2369         va_start(ap, fmt);
2370         ret = vasprintf(&newstr, fmt, ap);
2371         va_end(ap);
2372
2373         if (ret < 0)
2374                 goto error;
2375
2376         increased = False;
2377
2378         while ((*len)+ret >= *bufsize) {
2379                 increased = True;
2380                 *bufsize *= 2;
2381                 if (*bufsize >= (1024*1024*256))
2382                         goto error;
2383         }
2384
2385         if (increased) {
2386                 if (mem_ctx != NULL) {
2387                         *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
2388                                                        *bufsize);
2389                 } else {
2390                         *string = SMB_REALLOC_ARRAY(*string, char, *bufsize);
2391                 }
2392
2393                 if (*string == NULL) {
2394                         goto error;
2395                 }
2396         }
2397
2398         StrnCpy((*string)+(*len), newstr, ret);
2399         (*len) += ret;
2400         free(newstr);
2401         return;
2402
2403  error:
2404         *len = -1;
2405         *string = NULL;
2406 }
2407
2408 /*
2409    Returns the substring from src between the first occurrence of
2410    the char "front" and the first occurence of the char "back".
2411    Mallocs the return string which must be freed.  Not for use
2412    with wide character strings.
2413 */
2414 char *sstring_sub(const char *src, char front, char back)
2415 {
2416         char *temp1, *temp2, *temp3;
2417         ptrdiff_t len;
2418
2419         temp1 = strchr(src, front);
2420         if (temp1 == NULL) return NULL;
2421         temp2 = strchr(src, back);
2422         if (temp2 == NULL) return NULL;
2423         len = temp2 - temp1;
2424         if (len <= 0) return NULL;
2425         temp3 = (char*)SMB_MALLOC(len);
2426         if (temp3 == NULL) {
2427                 DEBUG(1,("Malloc failure in sstring_sub\n"));
2428                 return NULL;
2429         }
2430         memcpy(temp3, temp1+1, len-1);
2431         temp3[len-1] = '\0';
2432         return temp3;
2433 }
2434
2435 /********************************************************************
2436  Check a string for any occurrences of a specified list of invalid
2437  characters.
2438 ********************************************************************/
2439
2440 BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len )
2441 {
2442         int i;
2443
2444         for ( i=0; i<max_len && name[i]; i++ ) {
2445                 /* fail if strchr_m() finds one of the invalid characters */
2446                 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
2447                         return False;
2448                 }
2449         }
2450
2451         return True;
2452 }
2453