s3-lib Remove unused str_ascii_charnum()
[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    Copyright (C) James Peach     2006
9    Copyright (C) Jeremy Allison  1992-2007
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26
27 const char toupper_ascii_fast_table[128] = {
28         0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
29         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
30         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
31         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
32         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
33         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
34         0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
35         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
36 };
37
38 /**
39  * Case insensitive string compararison.
40  *
41  * iconv does not directly give us a way to compare strings in
42  * arbitrary unix character sets -- all we can is convert and then
43  * compare.  This is expensive.
44  *
45  * As an optimization, we do a first pass that considers only the
46  * prefix of the strings that is entirely 7-bit.  Within this, we
47  * check whether they have the same value.
48  *
49  * Hopefully this will often give the answer without needing to copy.
50  * In particular it should speed comparisons to literal ascii strings
51  * or comparisons of strings that are "obviously" different.
52  *
53  * If we find a non-ascii character we fall back to converting via
54  * iconv.
55  *
56  * This should never be slower than convering the whole thing, and
57  * often faster.
58  *
59  * A different optimization would be to compare for bitwise equality
60  * in the binary encoding.  (It would be possible thought hairy to do
61  * both simultaneously.)  But in that case if they turn out to be
62  * different, we'd need to restart the whole thing.
63  *
64  * Even better is to implement strcasecmp for each encoding and use a
65  * function pointer.
66  **/
67 int StrCaseCmp(const char *s, const char *t)
68 {
69
70         const char *ps, *pt;
71         size_t size;
72         smb_ucs2_t *buffer_s, *buffer_t;
73         int ret;
74
75         for (ps = s, pt = t; ; ps++, pt++) {
76                 char us, ut;
77
78                 if (!*ps && !*pt)
79                         return 0; /* both ended */
80                 else if (!*ps)
81                         return -1; /* s is a prefix */
82                 else if (!*pt)
83                         return +1; /* t is a prefix */
84                 else if ((*ps & 0x80) || (*pt & 0x80))
85                         /* not ascii anymore, do it the hard way
86                          * from here on in */
87                         break;
88
89                 us = toupper_ascii_fast(*ps);
90                 ut = toupper_ascii_fast(*pt);
91                 if (us == ut)
92                         continue;
93                 else if (us < ut)
94                         return -1;
95                 else if (us > ut)
96                         return +1;
97         }
98
99         if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
100                 return strcmp(ps, pt);
101                 /* Not quite the right answer, but finding the right one
102                    under this failure case is expensive, and it's pretty
103                    close */
104         }
105
106         if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
107                 TALLOC_FREE(buffer_s);
108                 return strcmp(ps, pt);
109                 /* Not quite the right answer, but finding the right one
110                    under this failure case is expensive, and it's pretty
111                    close */
112         }
113
114         ret = strcasecmp_w(buffer_s, buffer_t);
115         TALLOC_FREE(buffer_s);
116         TALLOC_FREE(buffer_t);
117         return ret;
118 }
119
120
121 /**
122  Case insensitive string compararison, length limited.
123 **/
124 int StrnCaseCmp(const char *s, const char *t, size_t len)
125 {
126         size_t n = 0;
127         const char *ps, *pt;
128         size_t size;
129         smb_ucs2_t *buffer_s, *buffer_t;
130         int ret;
131
132         for (ps = s, pt = t; n < len ; ps++, pt++, n++) {
133                 char us, ut;
134
135                 if (!*ps && !*pt)
136                         return 0; /* both ended */
137                 else if (!*ps)
138                         return -1; /* s is a prefix */
139                 else if (!*pt)
140                         return +1; /* t is a prefix */
141                 else if ((*ps & 0x80) || (*pt & 0x80))
142                         /* not ascii anymore, do it the
143                          * hard way from here on in */
144                         break;
145
146                 us = toupper_ascii_fast(*ps);
147                 ut = toupper_ascii_fast(*pt);
148                 if (us == ut)
149                         continue;
150                 else if (us < ut)
151                         return -1;
152                 else if (us > ut)
153                         return +1;
154         }
155
156         if (n == len) {
157                 return 0;
158         }
159
160         if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) {
161                 return strncmp(ps, pt, len-n);
162                 /* Not quite the right answer, but finding the right one
163                    under this failure case is expensive,
164                    and it's pretty close */
165         }
166
167         if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) {
168                 TALLOC_FREE(buffer_s);
169                 return strncmp(ps, pt, len-n);
170                 /* Not quite the right answer, but finding the right one
171                    under this failure case is expensive,
172                    and it's pretty close */
173         }
174
175         ret = strncasecmp_w(buffer_s, buffer_t, len-n);
176         TALLOC_FREE(buffer_s);
177         TALLOC_FREE(buffer_t);
178         return ret;
179 }
180
181 /**
182  * Compare 2 strings.
183  *
184  * @note The comparison is case-insensitive.
185  **/
186 bool strequal(const char *s1, const char *s2)
187 {
188         if (s1 == s2)
189                 return(true);
190         if (!s1 || !s2)
191                 return(false);
192
193         return(StrCaseCmp(s1,s2)==0);
194 }
195
196 /**
197  * Compare 2 strings up to and including the nth char.
198  *
199  * @note The comparison is case-insensitive.
200  **/
201 bool strnequal(const char *s1,const char *s2,size_t n)
202 {
203         if (s1 == s2)
204                 return(true);
205         if (!s1 || !s2 || !n)
206                 return(false);
207
208         return(StrnCaseCmp(s1,s2,n)==0);
209 }
210
211 /**
212  Convert a string to "normal" form.
213 **/
214
215 void strnorm(char *s, int case_default)
216 {
217         if (case_default == CASE_UPPER)
218                 strupper_m(s);
219         else
220                 strlower_m(s);
221 }
222
223 /**
224  *  Skip past some strings in a buffer - old version - no checks.
225  *  **/
226
227 char *push_skip_string(char *buf)
228 {
229         buf += strlen(buf) + 1;
230         return(buf);
231 }
232
233 /**
234  Skip past a string in a buffer. Buffer may not be
235  null terminated. end_ptr points to the first byte after
236  then end of the buffer.
237 **/
238
239 char *skip_string(const char *base, size_t len, char *buf)
240 {
241         const char *end_ptr = base + len;
242
243         if (end_ptr < base || !base || !buf || buf >= end_ptr) {
244                 return NULL;
245         }
246
247         /* Skip the string */
248         while (*buf) {
249                 buf++;
250                 if (buf >= end_ptr) {
251                         return NULL;
252                 }
253         }
254         /* Skip the '\0' */
255         buf++;
256         return buf;
257 }
258
259 /**
260  Count the number of characters in a string. Normally this will
261  be the same as the number of bytes in a string for single byte strings,
262  but will be different for multibyte.
263 **/
264
265 size_t str_charnum(const char *s)
266 {
267         size_t ret, converted_size;
268         smb_ucs2_t *tmpbuf2 = NULL;
269         if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
270                 return 0;
271         }
272         ret = strlen_w(tmpbuf2);
273         TALLOC_FREE(tmpbuf2);
274         return ret;
275 }
276
277 bool trim_char(char *s,char cfront,char cback)
278 {
279         bool ret = false;
280         char *ep;
281         char *fp = s;
282
283         /* Ignore null or empty strings. */
284         if (!s || (s[0] == '\0'))
285                 return false;
286
287         if (cfront) {
288                 while (*fp && *fp == cfront)
289                         fp++;
290                 if (!*fp) {
291                         /* We ate the string. */
292                         s[0] = '\0';
293                         return true;
294                 }
295                 if (fp != s)
296                         ret = true;
297         }
298
299         ep = fp + strlen(fp) - 1;
300         if (cback) {
301                 /* Attempt ascii only. Bail for mb strings. */
302                 while ((ep >= fp) && (*ep == cback)) {
303                         ret = true;
304                         if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
305                                 /* Could be mb... bail back to tim_string. */
306                                 char fs[2], bs[2];
307                                 if (cfront) {
308                                         fs[0] = cfront;
309                                         fs[1] = '\0';
310                                 }
311                                 bs[0] = cback;
312                                 bs[1] = '\0';
313                                 return trim_string(s, cfront ? fs : NULL, bs);
314                         } else {
315                                 ep--;
316                         }
317                 }
318                 if (ep < fp) {
319                         /* We ate the string. */
320                         s[0] = '\0';
321                         return true;
322                 }
323         }
324
325         ep[1] = '\0';
326         memmove(s, fp, ep-fp+2);
327         return ret;
328 }
329
330 /**
331  Safe string copy into a known length string. maxlength does not
332  include the terminating zero.
333 **/
334
335 char *safe_strcpy_fn(char *dest,
336                      const char *src,
337                      size_t maxlength)
338 {
339         size_t len;
340
341         if (!dest) {
342                 smb_panic("ERROR: NULL dest in safe_strcpy");
343         }
344
345         if (!src) {
346                 *dest = 0;
347                 return dest;
348         }
349
350         len = strnlen(src, maxlength+1);
351
352         if (len > maxlength) {
353                 DEBUG(0,("ERROR: string overflow by "
354                         "%lu (%lu - %lu) in safe_strcpy [%.50s]\n",
355                          (unsigned long)(len-maxlength), (unsigned long)len,
356                          (unsigned long)maxlength, src));
357                 len = maxlength;
358         }
359
360         memmove(dest, src, len);
361         dest[len] = 0;
362         return dest;
363 }
364
365 /**
366  Safe string cat into a string. maxlength does not
367  include the terminating zero.
368 **/
369 char *safe_strcat_fn(char *dest,
370                      const char *src,
371                      size_t maxlength)
372 {
373         size_t src_len, dest_len;
374
375         if (!dest) {
376                 smb_panic("ERROR: NULL dest in safe_strcat");
377         }
378
379         if (!src)
380                 return dest;
381
382         src_len = strnlen(src, maxlength + 1);
383         dest_len = strnlen(dest, maxlength + 1);
384
385         if (src_len + dest_len > maxlength) {
386                 DEBUG(0,("ERROR: string overflow by %d "
387                         "in safe_strcat [%.50s]\n",
388                          (int)(src_len + dest_len - maxlength), src));
389                 if (maxlength > dest_len) {
390                         memcpy(&dest[dest_len], src, maxlength - dest_len);
391                 }
392                 dest[maxlength] = 0;
393                 return NULL;
394         }
395
396         memcpy(&dest[dest_len], src, src_len);
397         dest[dest_len + src_len] = 0;
398         return dest;
399 }
400
401 /**
402  Paranoid strcpy into a buffer of given length (includes terminating
403  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
404  and replaces with '_'. Deliberately does *NOT* check for multibyte
405  characters. Treats src as an array of bytes, not as a multibyte
406  string. Any byte >0x7f is automatically converted to '_'.
407  other_safe_chars must also contain an ascii string (bytes<0x7f).
408 **/
409
410 char *alpha_strcpy(char *dest,
411                    const char *src,
412                    const char *other_safe_chars,
413                    size_t maxlength)
414 {
415         size_t len, i;
416
417         if (!dest) {
418                 smb_panic("ERROR: NULL dest in alpha_strcpy");
419         }
420
421         if (!src) {
422                 *dest = 0;
423                 return dest;
424         }
425
426         len = strlen(src);
427         if (len >= maxlength)
428                 len = maxlength - 1;
429
430         if (!other_safe_chars)
431                 other_safe_chars = "";
432
433         for(i = 0; i < len; i++) {
434                 int val = (src[i] & 0xff);
435                 if (val > 0x7f) {
436                         dest[i] = '_';
437                         continue;
438                 }
439                 if (isupper(val) || islower(val) ||
440                                 isdigit(val) || strchr(other_safe_chars, val))
441                         dest[i] = src[i];
442                 else
443                         dest[i] = '_';
444         }
445
446         dest[i] = '\0';
447
448         return dest;
449 }
450
451 /**
452  Like strncpy but always null terminates. Make sure there is room!
453  The variable n should always be one less than the available size.
454 **/
455 char *StrnCpy(char *dest,const char *src,size_t n)
456 {
457         char *d = dest;
458
459         if (!dest) {
460                 smb_panic("ERROR: NULL dest in StrnCpy");
461         }
462
463         if (!src) {
464                 *dest = 0;
465                 return(dest);
466         }
467
468         while (n-- && (*d = *src)) {
469                 d++;
470                 src++;
471         }
472
473         *d = 0;
474         return(dest);
475 }
476
477 #if 0
478 /**
479  Like strncpy but copies up to the character marker.  always null terminates.
480  returns a pointer to the character marker in the source string (src).
481 **/
482
483 static char *strncpyn(char *dest, const char *src, size_t n, char c)
484 {
485         char *p;
486         size_t str_len;
487
488         p = strchr_m(src, c);
489         if (p == NULL) {
490                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
491                 return NULL;
492         }
493
494         str_len = PTR_DIFF(p, src);
495         strncpy(dest, src, MIN(n, str_len));
496         dest[str_len] = '\0';
497
498         return p;
499 }
500 #endif
501
502 /**
503  Check if a string is part of a list.
504 **/
505
506 bool in_list(const char *s, const char *list, bool casesensitive)
507 {
508         char *tok = NULL;
509         bool ret = false;
510         TALLOC_CTX *frame;
511
512         if (!list) {
513                 return false;
514         }
515
516         frame = talloc_stackframe();
517         while (next_token_talloc(frame, &list, &tok,LIST_SEP)) {
518                 if (casesensitive) {
519                         if (strcmp(tok,s) == 0) {
520                                 ret = true;
521                                 break;
522                         }
523                 } else {
524                         if (StrCaseCmp(tok,s) == 0) {
525                                 ret = true;
526                                 break;
527                         }
528                 }
529         }
530         TALLOC_FREE(frame);
531         return ret;
532 }
533
534 /* this is used to prevent lots of mallocs of size 1 */
535 static const char null_string[] = "";
536
537 /**
538  Set a string value, allocing the space for the string
539 **/
540
541 static bool string_init(char **dest,const char *src)
542 {
543         size_t l;
544
545         if (!src)
546                 src = "";
547
548         l = strlen(src);
549
550         if (l == 0) {
551                 *dest = CONST_DISCARD(char*, null_string);
552         } else {
553                 (*dest) = SMB_STRDUP(src);
554                 if ((*dest) == NULL) {
555                         DEBUG(0,("Out of memory in string_init\n"));
556                         return false;
557                 }
558         }
559         return(true);
560 }
561
562 /**
563  Free a string value.
564 **/
565
566 void string_free(char **s)
567 {
568         if (!s || !(*s))
569                 return;
570         if (*s == null_string)
571                 *s = NULL;
572         SAFE_FREE(*s);
573 }
574
575 /**
576  Set a string value, deallocating any existing space, and allocing the space
577  for the string
578 **/
579
580 bool string_set(char **dest,const char *src)
581 {
582         string_free(dest);
583         return(string_init(dest,src));
584 }
585
586 /**
587  Substitute a string for a pattern in another string. Make sure there is
588  enough room!
589
590  This routine looks for pattern in s and replaces it with
591  insert. It may do multiple replacements or just one.
592
593  Any of " ; ' $ or ` in the insert string are replaced with _
594  if len==0 then the string cannot be extended. This is different from the old
595  use of len==0 which was for no length checks to be done.
596 **/
597
598 void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
599                  bool remove_unsafe_characters, bool replace_once,
600                  bool allow_trailing_dollar)
601 {
602         char *p;
603         ssize_t ls,lp,li, i;
604
605         if (!insert || !pattern || !*pattern || !s)
606                 return;
607
608         ls = (ssize_t)strlen(s);
609         lp = (ssize_t)strlen(pattern);
610         li = (ssize_t)strlen(insert);
611
612         if (len == 0)
613                 len = ls + 1; /* len is number of *bytes* */
614
615         while (lp <= ls && (p = strstr_m(s,pattern))) {
616                 if (ls + (li-lp) >= len) {
617                         DEBUG(0,("ERROR: string overflow by "
618                                 "%d in string_sub(%.50s, %d)\n",
619                                  (int)(ls + (li-lp) - len),
620                                  pattern, (int)len));
621                         break;
622                 }
623                 if (li != lp) {
624                         memmove(p+li,p+lp,strlen(p+lp)+1);
625                 }
626                 for (i=0;i<li;i++) {
627                         switch (insert[i]) {
628                         case '$':
629                                 /* allow a trailing $
630                                  * (as in machine accounts) */
631                                 if (allow_trailing_dollar && (i == li - 1 )) {
632                                         p[i] = insert[i];
633                                         break;
634                                 }
635                         case '`':
636                         case '"':
637                         case '\'':
638                         case ';':
639                         case '%':
640                         case '\r':
641                         case '\n':
642                                 if ( remove_unsafe_characters ) {
643                                         p[i] = '_';
644                                         /* yes this break should be here
645                                          * since we want to fall throw if
646                                          * not replacing unsafe chars */
647                                         break;
648                                 }
649                         default:
650                                 p[i] = insert[i];
651                         }
652                 }
653                 s = p + li;
654                 ls += (li-lp);
655
656                 if (replace_once)
657                         break;
658         }
659 }
660
661 void string_sub_once(char *s, const char *pattern,
662                 const char *insert, size_t len)
663 {
664         string_sub2( s, pattern, insert, len, true, true, false );
665 }
666
667 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
668 {
669         string_sub2( s, pattern, insert, len, true, false, false );
670 }
671
672 void fstring_sub(char *s,const char *pattern,const char *insert)
673 {
674         string_sub(s, pattern, insert, sizeof(fstring));
675 }
676
677 /**
678  Similar to string_sub2, but it will accept only allocated strings
679  and may realloc them so pay attention at what you pass on no
680  pointers inside strings, no const may be passed
681  as string.
682 **/
683
684 char *realloc_string_sub2(char *string,
685                         const char *pattern,
686                         const char *insert,
687                         bool remove_unsafe_characters,
688                         bool allow_trailing_dollar)
689 {
690         char *p, *in;
691         char *s;
692         ssize_t ls,lp,li,ld, i;
693
694         if (!insert || !pattern || !*pattern || !string || !*string)
695                 return NULL;
696
697         s = string;
698
699         in = SMB_STRDUP(insert);
700         if (!in) {
701                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
702                 return NULL;
703         }
704         ls = (ssize_t)strlen(s);
705         lp = (ssize_t)strlen(pattern);
706         li = (ssize_t)strlen(insert);
707         ld = li - lp;
708         for (i=0;i<li;i++) {
709                 switch (in[i]) {
710                         case '$':
711                                 /* allow a trailing $
712                                  * (as in machine accounts) */
713                                 if (allow_trailing_dollar && (i == li - 1 )) {
714                                         break;
715                                 }
716                         case '`':
717                         case '"':
718                         case '\'':
719                         case ';':
720                         case '%':
721                         case '\r':
722                         case '\n':
723                                 if ( remove_unsafe_characters ) {
724                                         in[i] = '_';
725                                         break;
726                                 }
727                         default:
728                                 /* ok */
729                                 break;
730                 }
731         }
732
733         while ((p = strstr_m(s,pattern))) {
734                 if (ld > 0) {
735                         int offset = PTR_DIFF(s,string);
736                         string = (char *)SMB_REALLOC(string, ls + ld + 1);
737                         if (!string) {
738                                 DEBUG(0, ("realloc_string_sub: "
739                                         "out of memory!\n"));
740                                 SAFE_FREE(in);
741                                 return NULL;
742                         }
743                         p = string + offset + (p - s);
744                 }
745                 if (li != lp) {
746                         memmove(p+li,p+lp,strlen(p+lp)+1);
747                 }
748                 memcpy(p, in, li);
749                 s = p + li;
750                 ls += ld;
751         }
752         SAFE_FREE(in);
753         return string;
754 }
755
756 char *realloc_string_sub(char *string,
757                         const char *pattern,
758                         const char *insert)
759 {
760         return realloc_string_sub2(string, pattern, insert, true, false);
761 }
762
763 /*
764  * Internal guts of talloc_string_sub and talloc_all_string_sub.
765  * talloc version of string_sub2.
766  */
767
768 char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
769                         const char *pattern,
770                         const char *insert,
771                         bool remove_unsafe_characters,
772                         bool replace_once,
773                         bool allow_trailing_dollar)
774 {
775         char *p, *in;
776         char *s;
777         char *string;
778         ssize_t ls,lp,li,ld, i;
779
780         if (!insert || !pattern || !*pattern || !src) {
781                 return NULL;
782         }
783
784         string = talloc_strdup(mem_ctx, src);
785         if (string == NULL) {
786                 DEBUG(0, ("talloc_string_sub2: "
787                         "talloc_strdup failed\n"));
788                 return NULL;
789         }
790
791         s = string;
792
793         in = SMB_STRDUP(insert);
794         if (!in) {
795                 DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
796                 return NULL;
797         }
798         ls = (ssize_t)strlen(s);
799         lp = (ssize_t)strlen(pattern);
800         li = (ssize_t)strlen(insert);
801         ld = li - lp;
802
803         for (i=0;i<li;i++) {
804                 switch (in[i]) {
805                         case '$':
806                                 /* allow a trailing $
807                                  * (as in machine accounts) */
808                                 if (allow_trailing_dollar && (i == li - 1 )) {
809                                         break;
810                                 }
811                         case '`':
812                         case '"':
813                         case '\'':
814                         case ';':
815                         case '%':
816                         case '\r':
817                         case '\n':
818                                 if (remove_unsafe_characters) {
819                                         in[i] = '_';
820                                         break;
821                                 }
822                         default:
823                                 /* ok */
824                                 break;
825                 }
826         }
827
828         while ((p = strstr_m(s,pattern))) {
829                 if (ld > 0) {
830                         int offset = PTR_DIFF(s,string);
831                         string = (char *)TALLOC_REALLOC(mem_ctx, string,
832                                                         ls + ld + 1);
833                         if (!string) {
834                                 DEBUG(0, ("talloc_string_sub: out of "
835                                           "memory!\n"));
836                                 SAFE_FREE(in);
837                                 return NULL;
838                         }
839                         p = string + offset + (p - s);
840                 }
841                 if (li != lp) {
842                         memmove(p+li,p+lp,strlen(p+lp)+1);
843                 }
844                 memcpy(p, in, li);
845                 s = p + li;
846                 ls += ld;
847
848                 if (replace_once) {
849                         break;
850                 }
851         }
852         SAFE_FREE(in);
853         return string;
854 }
855
856 /* Same as string_sub, but returns a talloc'ed string */
857
858 char *talloc_string_sub(TALLOC_CTX *mem_ctx,
859                         const char *src,
860                         const char *pattern,
861                         const char *insert)
862 {
863         return talloc_string_sub2(mem_ctx, src, pattern, insert,
864                         true, false, false);
865 }
866
867 /**
868  Similar to string_sub() but allows for any character to be substituted.
869  Use with caution!
870  if len==0 then the string cannot be extended. This is different from the old
871  use of len==0 which was for no length checks to be done.
872 **/
873
874 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
875 {
876         char *p;
877         ssize_t ls,lp,li;
878
879         if (!insert || !pattern || !s)
880                 return;
881
882         ls = (ssize_t)strlen(s);
883         lp = (ssize_t)strlen(pattern);
884         li = (ssize_t)strlen(insert);
885
886         if (!*pattern)
887                 return;
888
889         if (len == 0)
890                 len = ls + 1; /* len is number of *bytes* */
891
892         while (lp <= ls && (p = strstr_m(s,pattern))) {
893                 if (ls + (li-lp) >= len) {
894                         DEBUG(0,("ERROR: string overflow by "
895                                 "%d in all_string_sub(%.50s, %d)\n",
896                                  (int)(ls + (li-lp) - len),
897                                  pattern, (int)len));
898                         break;
899                 }
900                 if (li != lp) {
901                         memmove(p+li,p+lp,strlen(p+lp)+1);
902                 }
903                 memcpy(p, insert, li);
904                 s = p + li;
905                 ls += (li-lp);
906         }
907 }
908
909 char *talloc_all_string_sub(TALLOC_CTX *ctx,
910                                 const char *src,
911                                 const char *pattern,
912                                 const char *insert)
913 {
914         return talloc_string_sub2(ctx, src, pattern, insert,
915                         false, false, false);
916 }
917
918 /**
919  Write an octal as a string.
920 **/
921
922 char *octal_string(int i)
923 {
924         char *result;
925         if (i == -1) {
926                 result = talloc_strdup(talloc_tos(), "-1");
927         }
928         else {
929                 result = talloc_asprintf(talloc_tos(), "0%o", i);
930         }
931         SMB_ASSERT(result != NULL);
932         return result;
933 }
934
935
936 /**
937  Truncate a string at a specified length.
938 **/
939
940 char *string_truncate(char *s, unsigned int length)
941 {
942         if (s && strlen(s) > length)
943                 s[length] = 0;
944         return s;
945 }
946
947
948 /***********************************************************************
949  Return the equivalent of doing strrchr 'n' times - always going
950  backwards.
951 ***********************************************************************/
952
953 char *strnrchr_m(const char *s, char c, unsigned int n)
954 {
955         smb_ucs2_t *ws = NULL;
956         char *s2 = NULL;
957         smb_ucs2_t *p;
958         char *ret;
959         size_t converted_size;
960
961         if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
962                 /* Too hard to try and get right. */
963                 return NULL;
964         }
965         p = strnrchr_w(ws, UCS2_CHAR(c), n);
966         if (!p) {
967                 TALLOC_FREE(ws);
968                 return NULL;
969         }
970         *p = 0;
971         if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
972                 TALLOC_FREE(ws);
973                 /* Too hard to try and get right. */
974                 return NULL;
975         }
976         ret = (char *)(s+strlen(s2));
977         TALLOC_FREE(ws);
978         TALLOC_FREE(s2);
979         return ret;
980 }
981
982 /***********************************************************************
983  strstr_m - We convert via ucs2 for now.
984 ***********************************************************************/
985
986 char *strstr_m(const char *src, const char *findstr)
987 {
988         smb_ucs2_t *p;
989         smb_ucs2_t *src_w, *find_w;
990         const char *s;
991         char *s2;
992         char *retp;
993
994         size_t converted_size, findstr_len = 0;
995
996         /* for correctness */
997         if (!findstr[0]) {
998                 return (char*)src;
999         }
1000
1001         /* Samba does single character findstr calls a *lot*. */
1002         if (findstr[1] == '\0')
1003                 return strchr_m(src, *findstr);
1004
1005         /* We optimise for the ascii case, knowing that all our
1006            supported multi-byte character sets are ascii-compatible
1007            (ie. they match for the first 128 chars) */
1008
1009         for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1010                 if (*s == *findstr) {
1011                         if (!findstr_len)
1012                                 findstr_len = strlen(findstr);
1013
1014                         if (strncmp(s, findstr, findstr_len) == 0) {
1015                                 return (char *)s;
1016                         }
1017                 }
1018         }
1019
1020         if (!*s)
1021                 return NULL;
1022
1023 #if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
1024         /* 'make check' fails unless we do this */
1025
1026         /* With compose characters we must restart from the beginning. JRA. */
1027         s = src;
1028 #endif
1029
1030         if (!push_ucs2_talloc(talloc_tos(), &src_w, src, &converted_size)) {
1031                 DEBUG(0,("strstr_m: src malloc fail\n"));
1032                 return NULL;
1033         }
1034
1035         if (!push_ucs2_talloc(talloc_tos(), &find_w, findstr, &converted_size)) {
1036                 TALLOC_FREE(src_w);
1037                 DEBUG(0,("strstr_m: find malloc fail\n"));
1038                 return NULL;
1039         }
1040
1041         p = strstr_w(src_w, find_w);
1042
1043         if (!p) {
1044                 TALLOC_FREE(src_w);
1045                 TALLOC_FREE(find_w);
1046                 return NULL;
1047         }
1048
1049         *p = 0;
1050         if (!pull_ucs2_talloc(talloc_tos(), &s2, src_w, &converted_size)) {
1051                 TALLOC_FREE(src_w);
1052                 TALLOC_FREE(find_w);
1053                 DEBUG(0,("strstr_m: dest malloc fail\n"));
1054                 return NULL;
1055         }
1056         retp = (char *)(s+strlen(s2));
1057         TALLOC_FREE(src_w);
1058         TALLOC_FREE(find_w);
1059         TALLOC_FREE(s2);
1060         return retp;
1061 }
1062
1063 /**
1064  Convert a string to lower case.
1065 **/
1066
1067 void strlower_m(char *s)
1068 {
1069         size_t len;
1070         int errno_save;
1071
1072         /* this is quite a common operation, so we want it to be
1073            fast. We optimise for the ascii case, knowing that all our
1074            supported multi-byte character sets are ascii-compatible
1075            (ie. they match for the first 128 chars) */
1076
1077         while (*s && !(((unsigned char)s[0]) & 0x80)) {
1078                 *s = tolower_ascii((unsigned char)*s);
1079                 s++;
1080         }
1081
1082         if (!*s)
1083                 return;
1084
1085         /* I assume that lowercased string takes the same number of bytes
1086          * as source string even in UTF-8 encoding. (VIV) */
1087         len = strlen(s) + 1;
1088         errno_save = errno;
1089         errno = 0;
1090         unix_strlower(s,len,s,len);
1091         /* Catch mb conversion errors that may not terminate. */
1092         if (errno)
1093                 s[len-1] = '\0';
1094         errno = errno_save;
1095 }
1096
1097 /**
1098  Convert a string to upper case.
1099 **/
1100
1101 void strupper_m(char *s)
1102 {
1103         size_t len;
1104         int errno_save;
1105
1106         /* this is quite a common operation, so we want it to be
1107            fast. We optimise for the ascii case, knowing that all our
1108            supported multi-byte character sets are ascii-compatible
1109            (ie. they match for the first 128 chars) */
1110
1111         while (*s && !(((unsigned char)s[0]) & 0x80)) {
1112                 *s = toupper_ascii_fast((unsigned char)*s);
1113                 s++;
1114         }
1115
1116         if (!*s)
1117                 return;
1118
1119         /* I assume that lowercased string takes the same number of bytes
1120          * as source string even in multibyte encoding. (VIV) */
1121         len = strlen(s) + 1;
1122         errno_save = errno;
1123         errno = 0;
1124         unix_strupper(s,len,s,len);
1125         /* Catch mb conversion errors that may not terminate. */
1126         if (errno)
1127                 s[len-1] = '\0';
1128         errno = errno_save;
1129 }
1130
1131 /**
1132  Just a typesafety wrapper for snprintf into a fstring.
1133 **/
1134
1135 int fstr_sprintf(fstring s, const char *fmt, ...)
1136 {
1137         va_list ap;
1138         int ret;
1139
1140         va_start(ap, fmt);
1141         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1142         va_end(ap);
1143         return ret;
1144 }
1145
1146 /**
1147  List of Strings manipulation functions
1148 **/
1149
1150 #define S_LIST_ABS 16 /* List Allocation Block Size */
1151
1152 /******************************************************************************
1153  version of standard_sub_basic() for string lists; uses talloc_sub_basic()
1154  for the work
1155  *****************************************************************************/
1156
1157 bool str_list_sub_basic( char **list, const char *smb_name,
1158                          const char *domain_name )
1159 {
1160         TALLOC_CTX *ctx = list;
1161         char *s, *tmpstr;
1162
1163         while ( *list ) {
1164                 s = *list;
1165                 tmpstr = talloc_sub_basic(ctx, smb_name, domain_name, s);
1166                 if ( !tmpstr ) {
1167                         DEBUG(0,("str_list_sub_basic: "
1168                                 "alloc_sub_basic() return NULL!\n"));
1169                         return false;
1170                 }
1171
1172                 TALLOC_FREE(*list);
1173                 *list = tmpstr;
1174
1175                 list++;
1176         }
1177
1178         return true;
1179 }
1180
1181 /******************************************************************************
1182  substitute a specific pattern in a string list
1183  *****************************************************************************/
1184
1185 bool str_list_substitute(char **list, const char *pattern, const char *insert)
1186 {
1187         TALLOC_CTX *ctx = list;
1188         char *p, *s, *t;
1189         ssize_t ls, lp, li, ld, i, d;
1190
1191         if (!list)
1192                 return false;
1193         if (!pattern)
1194                 return false;
1195         if (!insert)
1196                 return false;
1197
1198         lp = (ssize_t)strlen(pattern);
1199         li = (ssize_t)strlen(insert);
1200         ld = li -lp;
1201
1202         while (*list) {
1203                 s = *list;
1204                 ls = (ssize_t)strlen(s);
1205
1206                 while ((p = strstr_m(s, pattern))) {
1207                         t = *list;
1208                         d = p -t;
1209                         if (ld) {
1210                                 t = TALLOC_ARRAY(ctx, char, ls +ld +1);
1211                                 if (!t) {
1212                                         DEBUG(0,("str_list_substitute: "
1213                                                 "Unable to allocate memory"));
1214                                         return false;
1215                                 }
1216                                 memcpy(t, *list, d);
1217                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1218                                 TALLOC_FREE(*list);
1219                                 *list = t;
1220                                 ls += ld;
1221                                 s = t +d +li;
1222                         }
1223
1224                         for (i = 0; i < li; i++) {
1225                                 switch (insert[i]) {
1226                                         case '`':
1227                                         case '"':
1228                                         case '\'':
1229                                         case ';':
1230                                         case '$':
1231                                         case '%':
1232                                         case '\r':
1233                                         case '\n':
1234                                                 t[d +i] = '_';
1235                                                 break;
1236                                         default:
1237                                                 t[d +i] = insert[i];
1238                                 }
1239                         }
1240                 }
1241
1242                 list++;
1243         }
1244
1245         return true;
1246 }
1247
1248
1249 #define IPSTR_LIST_SEP  ","
1250 #define IPSTR_LIST_CHAR ','
1251
1252 /**
1253  * Add ip string representation to ipstr list. Used also
1254  * as part of @function ipstr_list_make
1255  *
1256  * @param ipstr_list pointer to string containing ip list;
1257  *        MUST BE already allocated and IS reallocated if necessary
1258  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1259  *        as a result of reallocation)
1260  * @param ip IP address which is to be added to list
1261  * @return pointer to string appended with new ip and possibly
1262  *         reallocated to new length
1263  **/
1264
1265 static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service)
1266 {
1267         char *new_ipstr = NULL;
1268         char addr_buf[INET6_ADDRSTRLEN];
1269         int ret;
1270
1271         /* arguments checking */
1272         if (!ipstr_list || !service) {
1273                 return NULL;
1274         }
1275
1276         print_sockaddr(addr_buf,
1277                         sizeof(addr_buf),
1278                         &service->ss);
1279
1280         /* attempt to convert ip to a string and append colon separator to it */
1281         if (*ipstr_list) {
1282                 if (service->ss.ss_family == AF_INET) {
1283                         /* IPv4 */
1284                         ret = asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list,
1285                                        IPSTR_LIST_SEP, addr_buf,
1286                                        service->port);
1287                 } else {
1288                         /* IPv6 */
1289                         ret = asprintf(&new_ipstr, "%s%s[%s]:%d", *ipstr_list,
1290                                        IPSTR_LIST_SEP, addr_buf,
1291                                        service->port);
1292                 }
1293                 SAFE_FREE(*ipstr_list);
1294         } else {
1295                 if (service->ss.ss_family == AF_INET) {
1296                         /* IPv4 */
1297                         ret = asprintf(&new_ipstr, "%s:%d", addr_buf,
1298                                        service->port);
1299                 } else {
1300                         /* IPv6 */
1301                         ret = asprintf(&new_ipstr, "[%s]:%d", addr_buf,
1302                                        service->port);
1303                 }
1304         }
1305         if (ret == -1) {
1306                 return NULL;
1307         }
1308         *ipstr_list = new_ipstr;
1309         return *ipstr_list;
1310 }
1311
1312 /**
1313  * Allocate and initialise an ipstr list using ip adresses
1314  * passed as arguments.
1315  *
1316  * @param ipstr_list pointer to string meant to be allocated and set
1317  * @param ip_list array of ip addresses to place in the list
1318  * @param ip_count number of addresses stored in ip_list
1319  * @return pointer to allocated ip string
1320  **/
1321
1322 char *ipstr_list_make(char **ipstr_list,
1323                         const struct ip_service *ip_list,
1324                         int ip_count)
1325 {
1326         int i;
1327
1328         /* arguments checking */
1329         if (!ip_list || !ipstr_list) {
1330                 return 0;
1331         }
1332
1333         *ipstr_list = NULL;
1334
1335         /* process ip addresses given as arguments */
1336         for (i = 0; i < ip_count; i++) {
1337                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1338         }
1339
1340         return (*ipstr_list);
1341 }
1342
1343
1344 /**
1345  * Parse given ip string list into array of ip addresses
1346  * (as ip_service structures)
1347  *    e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
1348  *
1349  * @param ipstr ip string list to be parsed
1350  * @param ip_list pointer to array of ip addresses which is
1351  *        allocated by this function and must be freed by caller
1352  * @return number of successfully parsed addresses
1353  **/
1354
1355 int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list)
1356 {
1357         TALLOC_CTX *frame;
1358         char *token_str = NULL;
1359         size_t count;
1360         int i;
1361
1362         if (!ipstr_list || !ip_list)
1363                 return 0;
1364
1365         count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1366         if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
1367                 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n",
1368                                         (unsigned long)count));
1369                 return 0;
1370         }
1371
1372         frame = talloc_stackframe();
1373         for ( i=0; next_token_talloc(frame, &ipstr_list, &token_str,
1374                                 IPSTR_LIST_SEP) && i<count; i++ ) {
1375                 char *s = token_str;
1376                 char *p = strrchr(token_str, ':');
1377
1378                 if (p) {
1379                         *p = 0;
1380                         (*ip_list)[i].port = atoi(p+1);
1381                 }
1382
1383                 /* convert single token to ip address */
1384                 if (token_str[0] == '[') {
1385                         /* IPv6 address. */
1386                         s++;
1387                         p = strchr(token_str, ']');
1388                         if (!p) {
1389                                 continue;
1390                         }
1391                         *p = '\0';
1392                 }
1393                 if (!interpret_string_addr(&(*ip_list)[i].ss,
1394                                         s,
1395                                         AI_NUMERICHOST)) {
1396                         continue;
1397                 }
1398         }
1399         TALLOC_FREE(frame);
1400         return count;
1401 }
1402
1403 /**
1404  * Safely free ip string list
1405  *
1406  * @param ipstr_list ip string list to be freed
1407  **/
1408
1409 void ipstr_list_free(char* ipstr_list)
1410 {
1411         SAFE_FREE(ipstr_list);
1412 }
1413
1414 /* read a SMB_BIG_UINT from a string */
1415 uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1416 {
1417
1418         uint64_t val = (uint64_t)-1;
1419         const char *p = nptr;
1420
1421         if (!p) {
1422                 if (entptr) {
1423                         *entptr = p;
1424                 }
1425                 return val;
1426         }
1427
1428         while (*p && isspace(*p))
1429                 p++;
1430
1431         sscanf(p,"%"PRIu64,&val);
1432         if (entptr) {
1433                 while (*p && isdigit(*p))
1434                         p++;
1435                 *entptr = p;
1436         }
1437
1438         return val;
1439 }
1440
1441 /* Convert a size specification to a count of bytes. We accept the following
1442  * suffixes:
1443  *          bytes if there is no suffix
1444  *      kK  kibibytes
1445  *      mM  mebibytes
1446  *      gG  gibibytes
1447  *      tT  tibibytes
1448  *      pP  whatever the ISO name for petabytes is
1449  *
1450  *  Returns 0 if the string can't be converted.
1451  */
1452 SMB_OFF_T conv_str_size(const char * str)
1453 {
1454         SMB_OFF_T lval_orig;
1455         SMB_OFF_T lval;
1456         char * end;
1457
1458         if (str == NULL || *str == '\0') {
1459                 return 0;
1460         }
1461
1462 #ifdef HAVE_STRTOULL
1463         if (sizeof(SMB_OFF_T) == 8) {
1464                 lval = strtoull(str, &end, 10 /* base */);
1465         } else {
1466                 lval = strtoul(str, &end, 10 /* base */);
1467         }
1468 #else
1469         lval = strtoul(str, &end, 10 /* base */);
1470 #endif
1471
1472         if (end == NULL || end == str) {
1473                 return 0;
1474         }
1475
1476         if (*end == '\0') {
1477                 return lval;
1478         }
1479
1480         lval_orig = lval;
1481
1482         if (strwicmp(end, "K") == 0) {
1483                 lval *= (SMB_OFF_T)1024;
1484         } else if (strwicmp(end, "M") == 0) {
1485                 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
1486         } else if (strwicmp(end, "G") == 0) {
1487                 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
1488                          (SMB_OFF_T)1024);
1489         } else if (strwicmp(end, "T") == 0) {
1490                 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
1491                          (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
1492         } else if (strwicmp(end, "P") == 0) {
1493                 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
1494                          (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
1495                          (SMB_OFF_T)1024);
1496         } else {
1497                 return 0;
1498         }
1499
1500         /*
1501          * Primitive attempt to detect wrapping on platforms with
1502          * 4-byte SMB_OFF_T. It's better to let the caller handle a
1503          * failure than some random number.
1504          */
1505         if (lval_orig <= lval) {
1506                 return 0;
1507         }
1508
1509         return lval;
1510 }
1511
1512 void string_append(char **left, const char *right)
1513 {
1514         int new_len = strlen(right) + 1;
1515
1516         if (*left == NULL) {
1517                 *left = (char *)SMB_MALLOC(new_len);
1518                 if (*left == NULL) {
1519                         return;
1520                 }
1521                 *left[0] = '\0';
1522         } else {
1523                 new_len += strlen(*left);
1524                 *left = (char *)SMB_REALLOC(*left, new_len);
1525         }
1526
1527         if (*left == NULL) {
1528                 return;
1529         }
1530
1531         safe_strcat(*left, right, new_len-1);
1532 }
1533
1534 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
1535  * error checking in between. The indiation that something weird happened is
1536  * string==NULL */
1537
1538 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
1539                     size_t *bufsize, const char *fmt, ...)
1540 {
1541         va_list ap;
1542         char *newstr;
1543         int ret;
1544         bool increased;
1545
1546         /* len<0 is an internal marker that something failed */
1547         if (*len < 0)
1548                 goto error;
1549
1550         if (*string == NULL) {
1551                 if (*bufsize == 0)
1552                         *bufsize = 128;
1553
1554                 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
1555                 if (*string == NULL)
1556                         goto error;
1557         }
1558
1559         va_start(ap, fmt);
1560         ret = vasprintf(&newstr, fmt, ap);
1561         va_end(ap);
1562
1563         if (ret < 0)
1564                 goto error;
1565
1566         increased = false;
1567
1568         while ((*len)+ret >= *bufsize) {
1569                 increased = true;
1570                 *bufsize *= 2;
1571                 if (*bufsize >= (1024*1024*256))
1572                         goto error;
1573         }
1574
1575         if (increased) {
1576                 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
1577                                                *bufsize);
1578                 if (*string == NULL) {
1579                         goto error;
1580                 }
1581         }
1582
1583         StrnCpy((*string)+(*len), newstr, ret);
1584         (*len) += ret;
1585         free(newstr);
1586         return;
1587
1588  error:
1589         *len = -1;
1590         *string = NULL;
1591 }
1592
1593 /*
1594  * asprintf into a string and strupper_m it after that.
1595  */
1596
1597 int asprintf_strupper_m(char **strp, const char *fmt, ...)
1598 {
1599         va_list ap;
1600         char *result;
1601         int ret;
1602
1603         va_start(ap, fmt);
1604         ret = vasprintf(&result, fmt, ap);
1605         va_end(ap);
1606
1607         if (ret == -1)
1608                 return -1;
1609
1610         strupper_m(result);
1611         *strp = result;
1612         return ret;
1613 }
1614
1615 char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
1616 {
1617         va_list ap;
1618         char *ret;
1619
1620         va_start(ap, fmt);
1621         ret = talloc_vasprintf(t, fmt, ap);
1622         va_end(ap);
1623
1624         if (ret == NULL) {
1625                 return NULL;
1626         }
1627         strupper_m(ret);
1628         return ret;
1629 }
1630
1631 char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
1632 {
1633         va_list ap;
1634         char *ret;
1635
1636         va_start(ap, fmt);
1637         ret = talloc_vasprintf(t, fmt, ap);
1638         va_end(ap);
1639
1640         if (ret == NULL) {
1641                 return NULL;
1642         }
1643         strlower_m(ret);
1644         return ret;
1645 }
1646
1647
1648 /*
1649    Returns the substring from src between the first occurrence of
1650    the char "front" and the first occurence of the char "back".
1651    Mallocs the return string which must be freed.  Not for use
1652    with wide character strings.
1653 */
1654 char *sstring_sub(const char *src, char front, char back)
1655 {
1656         char *temp1, *temp2, *temp3;
1657         ptrdiff_t len;
1658
1659         temp1 = strchr(src, front);
1660         if (temp1 == NULL) return NULL;
1661         temp2 = strchr(src, back);
1662         if (temp2 == NULL) return NULL;
1663         len = temp2 - temp1;
1664         if (len <= 0) return NULL;
1665         temp3 = (char*)SMB_MALLOC(len);
1666         if (temp3 == NULL) {
1667                 DEBUG(1,("Malloc failure in sstring_sub\n"));
1668                 return NULL;
1669         }
1670         memcpy(temp3, temp1+1, len-1);
1671         temp3[len-1] = '\0';
1672         return temp3;
1673 }
1674
1675 /********************************************************************
1676  Check a string for any occurrences of a specified list of invalid
1677  characters.
1678 ********************************************************************/
1679
1680 bool validate_net_name( const char *name,
1681                 const char *invalid_chars,
1682                 int max_len)
1683 {
1684         int i;
1685
1686         if (!name) {
1687                 return false;
1688         }
1689
1690         for ( i=0; i<max_len && name[i]; i++ ) {
1691                 /* fail if strchr_m() finds one of the invalid characters */
1692                 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
1693                         return false;
1694                 }
1695         }
1696
1697         return true;
1698 }
1699
1700
1701 /*******************************************************************
1702  Add a shell escape character '\' to any character not in a known list
1703  of characters. UNIX charset format.
1704 *******************************************************************/
1705
1706 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
1707 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
1708
1709 char *escape_shell_string(const char *src)
1710 {
1711         size_t srclen = strlen(src);
1712         char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
1713         char *dest = ret;
1714         bool in_s_quote = false;
1715         bool in_d_quote = false;
1716         bool next_escaped = false;
1717
1718         if (!ret) {
1719                 return NULL;
1720         }
1721
1722         while (*src) {
1723                 size_t c_size;
1724                 codepoint_t c = next_codepoint(src, &c_size);
1725
1726                 if (c == INVALID_CODEPOINT) {
1727                         SAFE_FREE(ret);
1728                         return NULL;
1729                 }
1730
1731                 if (c_size > 1) {
1732                         memcpy(dest, src, c_size);
1733                         src += c_size;
1734                         dest += c_size;
1735                         next_escaped = false;
1736                         continue;
1737                 }
1738
1739                 /*
1740                  * Deal with backslash escaped state.
1741                  * This only lasts for one character.
1742                  */
1743
1744                 if (next_escaped) {
1745                         *dest++ = *src++;
1746                         next_escaped = false;
1747                         continue;
1748                 }
1749
1750                 /*
1751                  * Deal with single quote state. The
1752                  * only thing we care about is exiting
1753                  * this state.
1754                  */
1755
1756                 if (in_s_quote) {
1757                         if (*src == '\'') {
1758                                 in_s_quote = false;
1759                         }
1760                         *dest++ = *src++;
1761                         continue;
1762                 }
1763
1764                 /*
1765                  * Deal with double quote state. The most
1766                  * complex state. We must cope with \, meaning
1767                  * possibly escape next char (depending what it
1768                  * is), ", meaning exit this state, and possibly
1769                  * add an \ escape to any unprotected character
1770                  * (listed in INSIDE_DQUOTE_LIST).
1771                  */
1772
1773                 if (in_d_quote) {
1774                         if (*src == '\\') {
1775                                 /*
1776                                  * Next character might be escaped.
1777                                  * We have to peek. Inside double
1778                                  * quotes only INSIDE_DQUOTE_LIST
1779                                  * characters are escaped by a \.
1780                                  */
1781
1782                                 char nextchar;
1783
1784                                 c = next_codepoint(&src[1], &c_size);
1785                                 if (c == INVALID_CODEPOINT) {
1786                                         SAFE_FREE(ret);
1787                                         return NULL;
1788                                 }
1789                                 if (c_size > 1) {
1790                                         /*
1791                                          * Don't escape the next char.
1792                                          * Just copy the \.
1793                                          */
1794                                         *dest++ = *src++;
1795                                         continue;
1796                                 }
1797
1798                                 nextchar = src[1];
1799
1800                                 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
1801                                                         (int)nextchar)) {
1802                                         next_escaped = true;
1803                                 }
1804                                 *dest++ = *src++;
1805                                 continue;
1806                         }
1807
1808                         if (*src == '\"') {
1809                                 /* Exit double quote state. */
1810                                 in_d_quote = false;
1811                                 *dest++ = *src++;
1812                                 continue;
1813                         }
1814
1815                         /*
1816                          * We know the character isn't \ or ",
1817                          * so escape it if it's any of the other
1818                          * possible unprotected characters.
1819                          */
1820
1821                         if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
1822                                 *dest++ = '\\';
1823                         }
1824                         *dest++ = *src++;
1825                         continue;
1826                 }
1827
1828                 /*
1829                  * From here to the end of the loop we're
1830                  * not in the single or double quote state.
1831                  */
1832
1833                 if (*src == '\\') {
1834                         /* Next character must be escaped. */
1835                         next_escaped = true;
1836                         *dest++ = *src++;
1837                         continue;
1838                 }
1839
1840                 if (*src == '\'') {
1841                         /* Go into single quote state. */
1842                         in_s_quote = true;
1843                         *dest++ = *src++;
1844                         continue;
1845                 }
1846
1847                 if (*src == '\"') {
1848                         /* Go into double quote state. */
1849                         in_d_quote = true;
1850                         *dest++ = *src++;
1851                         continue;
1852                 }
1853
1854                 /* Check if we need to escape the character. */
1855
1856                 if (!strchr(INCLUDE_LIST, (int)*src)) {
1857                         *dest++ = '\\';
1858                 }
1859                 *dest++ = *src++;
1860         }
1861         *dest++ = '\0';
1862         return ret;
1863 }
1864
1865 /***************************************************
1866  str_list_make, v3 version. The v4 version does not
1867  look at quoted strings with embedded blanks, so
1868  do NOT merge this function please!
1869 ***************************************************/
1870
1871 #define S_LIST_ABS 16 /* List Allocation Block Size */
1872
1873 char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
1874         const char *sep)
1875 {
1876         char **list;
1877         const char *str;
1878         char *s, *tok;
1879         int num, lsize;
1880
1881         if (!string || !*string)
1882                 return NULL;
1883
1884         list = TALLOC_ARRAY(mem_ctx, char *, S_LIST_ABS+1);
1885         if (list == NULL) {
1886                 return NULL;
1887         }
1888         lsize = S_LIST_ABS;
1889
1890         s = talloc_strdup(list, string);
1891         if (s == NULL) {
1892                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1893                 TALLOC_FREE(list);
1894                 return NULL;
1895         }
1896         if (!sep) sep = LIST_SEP;
1897
1898         num = 0;
1899         str = s;
1900
1901         while (next_token_talloc(list, &str, &tok, sep)) {
1902
1903                 if (num == lsize) {
1904                         char **tmp;
1905
1906                         lsize += S_LIST_ABS;
1907
1908                         tmp = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *,
1909                                                    lsize + 1);
1910                         if (tmp == NULL) {
1911                                 DEBUG(0,("str_list_make: "
1912                                         "Unable to allocate memory"));
1913                                 TALLOC_FREE(list);
1914                                 return NULL;
1915                         }
1916
1917                         list = tmp;
1918
1919                         memset (&list[num], 0,
1920                                 ((sizeof(char**)) * (S_LIST_ABS +1)));
1921                 }
1922
1923                 list[num] = tok;
1924                 num += 1;
1925         }
1926
1927         list[num] = NULL;
1928
1929         TALLOC_FREE(s);
1930         return list;
1931 }
1932
1933 char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
1934 {
1935         fstring tmp;
1936
1937         alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
1938         return talloc_strdup(mem_ctx, tmp);
1939 }