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