s3-lib Replace StrnCaseCmp() with strncasecmp_m()
[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  * Compare 2 strings up to and including the nth char.
40  *
41  * @note The comparison is case-insensitive.
42  **/
43 bool strnequal(const char *s1,const char *s2,size_t n)
44 {
45         if (s1 == s2)
46                 return(true);
47         if (!s1 || !s2 || !n)
48                 return(false);
49
50         return(strncasecmp_m(s1,s2,n)==0);
51 }
52
53 /**
54  Convert a string to "normal" form.
55 **/
56
57 void strnorm(char *s, int case_default)
58 {
59         if (case_default == CASE_UPPER)
60                 strupper_m(s);
61         else
62                 strlower_m(s);
63 }
64
65 /**
66  *  Skip past some strings in a buffer - old version - no checks.
67  *  **/
68
69 char *push_skip_string(char *buf)
70 {
71         buf += strlen(buf) + 1;
72         return(buf);
73 }
74
75 /**
76  Skip past a string in a buffer. Buffer may not be
77  null terminated. end_ptr points to the first byte after
78  then end of the buffer.
79 **/
80
81 char *skip_string(const char *base, size_t len, char *buf)
82 {
83         const char *end_ptr = base + len;
84
85         if (end_ptr < base || !base || !buf || buf >= end_ptr) {
86                 return NULL;
87         }
88
89         /* Skip the string */
90         while (*buf) {
91                 buf++;
92                 if (buf >= end_ptr) {
93                         return NULL;
94                 }
95         }
96         /* Skip the '\0' */
97         buf++;
98         return buf;
99 }
100
101 /**
102  Count the number of characters in a string. Normally this will
103  be the same as the number of bytes in a string for single byte strings,
104  but will be different for multibyte.
105 **/
106
107 size_t str_charnum(const char *s)
108 {
109         size_t ret, converted_size;
110         smb_ucs2_t *tmpbuf2 = NULL;
111         if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
112                 return 0;
113         }
114         ret = strlen_w(tmpbuf2);
115         TALLOC_FREE(tmpbuf2);
116         return ret;
117 }
118
119 bool trim_char(char *s,char cfront,char cback)
120 {
121         bool ret = false;
122         char *ep;
123         char *fp = s;
124
125         /* Ignore null or empty strings. */
126         if (!s || (s[0] == '\0'))
127                 return false;
128
129         if (cfront) {
130                 while (*fp && *fp == cfront)
131                         fp++;
132                 if (!*fp) {
133                         /* We ate the string. */
134                         s[0] = '\0';
135                         return true;
136                 }
137                 if (fp != s)
138                         ret = true;
139         }
140
141         ep = fp + strlen(fp) - 1;
142         if (cback) {
143                 /* Attempt ascii only. Bail for mb strings. */
144                 while ((ep >= fp) && (*ep == cback)) {
145                         ret = true;
146                         if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
147                                 /* Could be mb... bail back to tim_string. */
148                                 char fs[2], bs[2];
149                                 if (cfront) {
150                                         fs[0] = cfront;
151                                         fs[1] = '\0';
152                                 }
153                                 bs[0] = cback;
154                                 bs[1] = '\0';
155                                 return trim_string(s, cfront ? fs : NULL, bs);
156                         } else {
157                                 ep--;
158                         }
159                 }
160                 if (ep < fp) {
161                         /* We ate the string. */
162                         s[0] = '\0';
163                         return true;
164                 }
165         }
166
167         ep[1] = '\0';
168         memmove(s, fp, ep-fp+2);
169         return ret;
170 }
171
172 /**
173  Like strncpy but always null terminates. Make sure there is room!
174  The variable n should always be one less than the available size.
175 **/
176 char *StrnCpy(char *dest,const char *src,size_t n)
177 {
178         char *d = dest;
179
180         if (!dest) {
181                 smb_panic("ERROR: NULL dest in StrnCpy");
182         }
183
184         if (!src) {
185                 *dest = 0;
186                 return(dest);
187         }
188
189         while (n-- && (*d = *src)) {
190                 d++;
191                 src++;
192         }
193
194         *d = 0;
195         return(dest);
196 }
197
198 /**
199  Check if a string is part of a list.
200 **/
201
202 bool in_list(const char *s, const char *list, bool casesensitive)
203 {
204         char *tok = NULL;
205         bool ret = false;
206         TALLOC_CTX *frame;
207
208         if (!list) {
209                 return false;
210         }
211
212         frame = talloc_stackframe();
213         while (next_token_talloc(frame, &list, &tok,LIST_SEP)) {
214                 if (casesensitive) {
215                         if (strcmp(tok,s) == 0) {
216                                 ret = true;
217                                 break;
218                         }
219                 } else {
220                         if (strcasecmp_m(tok,s) == 0) {
221                                 ret = true;
222                                 break;
223                         }
224                 }
225         }
226         TALLOC_FREE(frame);
227         return ret;
228 }
229
230 /* this is used to prevent lots of mallocs of size 1 */
231 static const char null_string[] = "";
232
233 /**
234  Set a string value, allocing the space for the string
235 **/
236
237 static bool string_init(char **dest,const char *src)
238 {
239         size_t l;
240
241         if (!src)
242                 src = "";
243
244         l = strlen(src);
245
246         if (l == 0) {
247                 *dest = discard_const_p(char, null_string);
248         } else {
249                 (*dest) = SMB_STRDUP(src);
250                 if ((*dest) == NULL) {
251                         DEBUG(0,("Out of memory in string_init\n"));
252                         return false;
253                 }
254         }
255         return(true);
256 }
257
258 /**
259  Free a string value.
260 **/
261
262 void string_free(char **s)
263 {
264         if (!s || !(*s))
265                 return;
266         if (*s == null_string)
267                 *s = NULL;
268         SAFE_FREE(*s);
269 }
270
271 /**
272  Set a string value, deallocating any existing space, and allocing the space
273  for the string
274 **/
275
276 bool string_set(char **dest,const char *src)
277 {
278         string_free(dest);
279         return(string_init(dest,src));
280 }
281
282 void fstring_sub(char *s,const char *pattern,const char *insert)
283 {
284         string_sub(s, pattern, insert, sizeof(fstring));
285 }
286
287 /**
288  Similar to string_sub2, but it will accept only allocated strings
289  and may realloc them so pay attention at what you pass on no
290  pointers inside strings, no const may be passed
291  as string.
292 **/
293
294 char *realloc_string_sub2(char *string,
295                         const char *pattern,
296                         const char *insert,
297                         bool remove_unsafe_characters,
298                         bool allow_trailing_dollar)
299 {
300         char *p, *in;
301         char *s;
302         ssize_t ls,lp,li,ld, i;
303
304         if (!insert || !pattern || !*pattern || !string || !*string)
305                 return NULL;
306
307         s = string;
308
309         in = SMB_STRDUP(insert);
310         if (!in) {
311                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
312                 return NULL;
313         }
314         ls = (ssize_t)strlen(s);
315         lp = (ssize_t)strlen(pattern);
316         li = (ssize_t)strlen(insert);
317         ld = li - lp;
318         for (i=0;i<li;i++) {
319                 switch (in[i]) {
320                         case '$':
321                                 /* allow a trailing $
322                                  * (as in machine accounts) */
323                                 if (allow_trailing_dollar && (i == li - 1 )) {
324                                         break;
325                                 }
326                         case '`':
327                         case '"':
328                         case '\'':
329                         case ';':
330                         case '%':
331                         case '\r':
332                         case '\n':
333                                 if ( remove_unsafe_characters ) {
334                                         in[i] = '_';
335                                         break;
336                                 }
337                         default:
338                                 /* ok */
339                                 break;
340                 }
341         }
342
343         while ((p = strstr_m(s,pattern))) {
344                 if (ld > 0) {
345                         int offset = PTR_DIFF(s,string);
346                         string = (char *)SMB_REALLOC(string, ls + ld + 1);
347                         if (!string) {
348                                 DEBUG(0, ("realloc_string_sub: "
349                                         "out of memory!\n"));
350                                 SAFE_FREE(in);
351                                 return NULL;
352                         }
353                         p = string + offset + (p - s);
354                 }
355                 if (li != lp) {
356                         memmove(p+li,p+lp,strlen(p+lp)+1);
357                 }
358                 memcpy(p, in, li);
359                 s = p + li;
360                 ls += ld;
361         }
362         SAFE_FREE(in);
363         return string;
364 }
365
366 char *realloc_string_sub(char *string,
367                         const char *pattern,
368                         const char *insert)
369 {
370         return realloc_string_sub2(string, pattern, insert, true, false);
371 }
372
373 /*
374  * Internal guts of talloc_string_sub and talloc_all_string_sub.
375  * talloc version of string_sub2.
376  */
377
378 char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
379                         const char *pattern,
380                         const char *insert,
381                         bool remove_unsafe_characters,
382                         bool replace_once,
383                         bool allow_trailing_dollar)
384 {
385         char *p, *in;
386         char *s;
387         char *string;
388         ssize_t ls,lp,li,ld, i;
389
390         if (!insert || !pattern || !*pattern || !src) {
391                 return NULL;
392         }
393
394         string = talloc_strdup(mem_ctx, src);
395         if (string == NULL) {
396                 DEBUG(0, ("talloc_string_sub2: "
397                         "talloc_strdup failed\n"));
398                 return NULL;
399         }
400
401         s = string;
402
403         in = SMB_STRDUP(insert);
404         if (!in) {
405                 DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
406                 return NULL;
407         }
408         ls = (ssize_t)strlen(s);
409         lp = (ssize_t)strlen(pattern);
410         li = (ssize_t)strlen(insert);
411         ld = li - lp;
412
413         for (i=0;i<li;i++) {
414                 switch (in[i]) {
415                         case '$':
416                                 /* allow a trailing $
417                                  * (as in machine accounts) */
418                                 if (allow_trailing_dollar && (i == li - 1 )) {
419                                         break;
420                                 }
421                         case '`':
422                         case '"':
423                         case '\'':
424                         case ';':
425                         case '%':
426                         case '\r':
427                         case '\n':
428                                 if (remove_unsafe_characters) {
429                                         in[i] = '_';
430                                         break;
431                                 }
432                         default:
433                                 /* ok */
434                                 break;
435                 }
436         }
437
438         while ((p = strstr_m(s,pattern))) {
439                 if (ld > 0) {
440                         int offset = PTR_DIFF(s,string);
441                         string = (char *)TALLOC_REALLOC(mem_ctx, string,
442                                                         ls + ld + 1);
443                         if (!string) {
444                                 DEBUG(0, ("talloc_string_sub: out of "
445                                           "memory!\n"));
446                                 SAFE_FREE(in);
447                                 return NULL;
448                         }
449                         p = string + offset + (p - s);
450                 }
451                 if (li != lp) {
452                         memmove(p+li,p+lp,strlen(p+lp)+1);
453                 }
454                 memcpy(p, in, li);
455                 s = p + li;
456                 ls += ld;
457
458                 if (replace_once) {
459                         break;
460                 }
461         }
462         SAFE_FREE(in);
463         return string;
464 }
465
466 /* Same as string_sub, but returns a talloc'ed string */
467
468 char *talloc_string_sub(TALLOC_CTX *mem_ctx,
469                         const char *src,
470                         const char *pattern,
471                         const char *insert)
472 {
473         return talloc_string_sub2(mem_ctx, src, pattern, insert,
474                         true, false, false);
475 }
476
477 char *talloc_all_string_sub(TALLOC_CTX *ctx,
478                                 const char *src,
479                                 const char *pattern,
480                                 const char *insert)
481 {
482         return talloc_string_sub2(ctx, src, pattern, insert,
483                         false, false, false);
484 }
485
486 /**
487  Write an octal as a string.
488 **/
489
490 char *octal_string(int i)
491 {
492         char *result;
493         if (i == -1) {
494                 result = talloc_strdup(talloc_tos(), "-1");
495         }
496         else {
497                 result = talloc_asprintf(talloc_tos(), "0%o", i);
498         }
499         SMB_ASSERT(result != NULL);
500         return result;
501 }
502
503
504 /**
505  Truncate a string at a specified length.
506 **/
507
508 char *string_truncate(char *s, unsigned int length)
509 {
510         if (s && strlen(s) > length)
511                 s[length] = 0;
512         return s;
513 }
514
515
516 /***********************************************************************
517  Return the equivalent of doing strrchr 'n' times - always going
518  backwards.
519 ***********************************************************************/
520
521 char *strnrchr_m(const char *s, char c, unsigned int n)
522 {
523         smb_ucs2_t *ws = NULL;
524         char *s2 = NULL;
525         smb_ucs2_t *p;
526         char *ret;
527         size_t converted_size;
528
529         if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
530                 /* Too hard to try and get right. */
531                 return NULL;
532         }
533         p = strnrchr_w(ws, UCS2_CHAR(c), n);
534         if (!p) {
535                 TALLOC_FREE(ws);
536                 return NULL;
537         }
538         *p = 0;
539         if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
540                 TALLOC_FREE(ws);
541                 /* Too hard to try and get right. */
542                 return NULL;
543         }
544         ret = discard_const_p(char, (s+strlen(s2)));
545         TALLOC_FREE(ws);
546         TALLOC_FREE(s2);
547         return ret;
548 }
549
550 static bool unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
551 {
552         size_t size;
553         smb_ucs2_t *buffer = NULL;
554         bool ret;
555
556         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
557                                    (void **)(void *)&buffer, &size))
558         {
559                 smb_panic("failed to create UCS2 buffer");
560         }
561         if (!strlower_w(buffer) && (dest == src)) {
562                 TALLOC_FREE(buffer);
563                 return srclen;
564         }
565         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
566         TALLOC_FREE(buffer);
567         return ret;
568 }
569
570 #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
571
572 /**
573  Convert a string to lower case.
574 **/
575 _PUBLIC_ void strlower_m(char *s)
576 {
577         char *d;
578         struct smb_iconv_handle *iconv_handle;
579
580         iconv_handle = get_iconv_handle();
581
582         d = s;
583
584         while (*s) {
585                 size_t c_size, c_size2;
586                 codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
587                 c_size2 = push_codepoint_handle(iconv_handle, d, tolower_m(c));
588                 if (c_size2 > c_size) {
589                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
590                                  c, tolower_m(c), (int)c_size, (int)c_size2));
591                         smb_panic("codepoint expansion in strlower_m\n");
592                 }
593                 s += c_size;
594                 d += c_size2;
595         }
596         *d = 0;
597 }
598
599 #endif
600
601 /**
602  Convert a string to lower case.
603 **/
604
605 void strlower_m(char *s)
606 {
607         size_t len;
608         int errno_save;
609
610         /* this is quite a common operation, so we want it to be
611            fast. We optimise for the ascii case, knowing that all our
612            supported multi-byte character sets are ascii-compatible
613            (ie. they match for the first 128 chars) */
614
615         while (*s && !(((unsigned char)s[0]) & 0x80)) {
616                 *s = tolower_ascii((unsigned char)*s);
617                 s++;
618         }
619
620         if (!*s)
621                 return;
622
623         /* I assume that lowercased string takes the same number of bytes
624          * as source string even in UTF-8 encoding. (VIV) */
625         len = strlen(s) + 1;
626         errno_save = errno;
627         errno = 0;
628         unix_strlower(s,len,s,len);
629         /* Catch mb conversion errors that may not terminate. */
630         if (errno)
631                 s[len-1] = '\0';
632         errno = errno_save;
633 }
634
635 static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
636 {
637         size_t size;
638         smb_ucs2_t *buffer;
639         bool ret;
640
641         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
642                 return (size_t)-1;
643         }
644
645         if (!strupper_w(buffer) && (dest == src)) {
646                 TALLOC_FREE(buffer);
647                 return srclen;
648         }
649
650         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
651         TALLOC_FREE(buffer);
652         return ret;
653 }
654
655 #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
656
657 /**
658  Convert a string to UPPER case.
659 **/
660 _PUBLIC_ void strupper_m(char *s)
661 {
662         char *d;
663         struct smb_iconv_handle *iconv_handle;
664
665         iconv_handle = get_iconv_handle();
666
667         d = s;
668
669         while (*s) {
670                 size_t c_size, c_size2;
671                 codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
672                 c_size2 = push_codepoint_handle(iconv_handle, d, toupper_m(c));
673                 if (c_size2 > c_size) {
674                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
675                                  c, toupper_m(c), (int)c_size, (int)c_size2));
676                         smb_panic("codepoint expansion in strupper_m\n");
677                 }
678                 s += c_size;
679                 d += c_size2;
680         }
681         *d = 0;
682 }
683
684 #endif
685
686 /**
687  Convert a string to upper case.
688 **/
689
690 void strupper_m(char *s)
691 {
692         size_t len;
693         int errno_save;
694
695         /* this is quite a common operation, so we want it to be
696            fast. We optimise for the ascii case, knowing that all our
697            supported multi-byte character sets are ascii-compatible
698            (ie. they match for the first 128 chars) */
699
700         while (*s && !(((unsigned char)s[0]) & 0x80)) {
701                 *s = toupper_ascii_fast((unsigned char)*s);
702                 s++;
703         }
704
705         if (!*s)
706                 return;
707
708         /* I assume that lowercased string takes the same number of bytes
709          * as source string even in multibyte encoding. (VIV) */
710         len = strlen(s) + 1;
711         errno_save = errno;
712         errno = 0;
713         unix_strupper(s,len,s,len);
714         /* Catch mb conversion errors that may not terminate. */
715         if (errno)
716                 s[len-1] = '\0';
717         errno = errno_save;
718 }
719
720 /**
721  Just a typesafety wrapper for snprintf into a fstring.
722 **/
723
724 int fstr_sprintf(fstring s, const char *fmt, ...)
725 {
726         va_list ap;
727         int ret;
728
729         va_start(ap, fmt);
730         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
731         va_end(ap);
732         return ret;
733 }
734
735 /**
736  List of Strings manipulation functions
737 **/
738
739 #define S_LIST_ABS 16 /* List Allocation Block Size */
740
741 /******************************************************************************
742  version of standard_sub_basic() for string lists; uses talloc_sub_basic()
743  for the work
744  *****************************************************************************/
745
746 bool str_list_sub_basic( char **list, const char *smb_name,
747                          const char *domain_name )
748 {
749         TALLOC_CTX *ctx = list;
750         char *s, *tmpstr;
751
752         while ( *list ) {
753                 s = *list;
754                 tmpstr = talloc_sub_basic(ctx, smb_name, domain_name, s);
755                 if ( !tmpstr ) {
756                         DEBUG(0,("str_list_sub_basic: "
757                                 "alloc_sub_basic() return NULL!\n"));
758                         return false;
759                 }
760
761                 TALLOC_FREE(*list);
762                 *list = tmpstr;
763
764                 list++;
765         }
766
767         return true;
768 }
769
770 /******************************************************************************
771  substitute a specific pattern in a string list
772  *****************************************************************************/
773
774 bool str_list_substitute(char **list, const char *pattern, const char *insert)
775 {
776         TALLOC_CTX *ctx = list;
777         char *p, *s, *t;
778         ssize_t ls, lp, li, ld, i, d;
779
780         if (!list)
781                 return false;
782         if (!pattern)
783                 return false;
784         if (!insert)
785                 return false;
786
787         lp = (ssize_t)strlen(pattern);
788         li = (ssize_t)strlen(insert);
789         ld = li -lp;
790
791         while (*list) {
792                 s = *list;
793                 ls = (ssize_t)strlen(s);
794
795                 while ((p = strstr_m(s, pattern))) {
796                         t = *list;
797                         d = p -t;
798                         if (ld) {
799                                 t = TALLOC_ARRAY(ctx, char, ls +ld +1);
800                                 if (!t) {
801                                         DEBUG(0,("str_list_substitute: "
802                                                 "Unable to allocate memory"));
803                                         return false;
804                                 }
805                                 memcpy(t, *list, d);
806                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
807                                 TALLOC_FREE(*list);
808                                 *list = t;
809                                 ls += ld;
810                                 s = t +d +li;
811                         }
812
813                         for (i = 0; i < li; i++) {
814                                 switch (insert[i]) {
815                                         case '`':
816                                         case '"':
817                                         case '\'':
818                                         case ';':
819                                         case '$':
820                                         case '%':
821                                         case '\r':
822                                         case '\n':
823                                                 t[d +i] = '_';
824                                                 break;
825                                         default:
826                                                 t[d +i] = insert[i];
827                                 }
828                         }
829                 }
830
831                 list++;
832         }
833
834         return true;
835 }
836
837
838 #define IPSTR_LIST_SEP  ","
839 #define IPSTR_LIST_CHAR ','
840
841 /**
842  * Add ip string representation to ipstr list. Used also
843  * as part of @function ipstr_list_make
844  *
845  * @param ipstr_list pointer to string containing ip list;
846  *        MUST BE already allocated and IS reallocated if necessary
847  * @param ipstr_size pointer to current size of ipstr_list (might be changed
848  *        as a result of reallocation)
849  * @param ip IP address which is to be added to list
850  * @return pointer to string appended with new ip and possibly
851  *         reallocated to new length
852  **/
853
854 static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service)
855 {
856         char *new_ipstr = NULL;
857         char addr_buf[INET6_ADDRSTRLEN];
858         int ret;
859
860         /* arguments checking */
861         if (!ipstr_list || !service) {
862                 return NULL;
863         }
864
865         print_sockaddr(addr_buf,
866                         sizeof(addr_buf),
867                         &service->ss);
868
869         /* attempt to convert ip to a string and append colon separator to it */
870         if (*ipstr_list) {
871                 if (service->ss.ss_family == AF_INET) {
872                         /* IPv4 */
873                         ret = asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list,
874                                        IPSTR_LIST_SEP, addr_buf,
875                                        service->port);
876                 } else {
877                         /* IPv6 */
878                         ret = asprintf(&new_ipstr, "%s%s[%s]:%d", *ipstr_list,
879                                        IPSTR_LIST_SEP, addr_buf,
880                                        service->port);
881                 }
882                 SAFE_FREE(*ipstr_list);
883         } else {
884                 if (service->ss.ss_family == AF_INET) {
885                         /* IPv4 */
886                         ret = asprintf(&new_ipstr, "%s:%d", addr_buf,
887                                        service->port);
888                 } else {
889                         /* IPv6 */
890                         ret = asprintf(&new_ipstr, "[%s]:%d", addr_buf,
891                                        service->port);
892                 }
893         }
894         if (ret == -1) {
895                 return NULL;
896         }
897         *ipstr_list = new_ipstr;
898         return *ipstr_list;
899 }
900
901 /**
902  * Allocate and initialise an ipstr list using ip adresses
903  * passed as arguments.
904  *
905  * @param ipstr_list pointer to string meant to be allocated and set
906  * @param ip_list array of ip addresses to place in the list
907  * @param ip_count number of addresses stored in ip_list
908  * @return pointer to allocated ip string
909  **/
910
911 char *ipstr_list_make(char **ipstr_list,
912                         const struct ip_service *ip_list,
913                         int ip_count)
914 {
915         int i;
916
917         /* arguments checking */
918         if (!ip_list || !ipstr_list) {
919                 return 0;
920         }
921
922         *ipstr_list = NULL;
923
924         /* process ip addresses given as arguments */
925         for (i = 0; i < ip_count; i++) {
926                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
927         }
928
929         return (*ipstr_list);
930 }
931
932
933 /**
934  * Parse given ip string list into array of ip addresses
935  * (as ip_service structures)
936  *    e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ...
937  *
938  * @param ipstr ip string list to be parsed
939  * @param ip_list pointer to array of ip addresses which is
940  *        allocated by this function and must be freed by caller
941  * @return number of successfully parsed addresses
942  **/
943
944 int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list)
945 {
946         TALLOC_CTX *frame;
947         char *token_str = NULL;
948         size_t count;
949         int i;
950
951         if (!ipstr_list || !ip_list)
952                 return 0;
953
954         count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
955         if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
956                 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n",
957                                         (unsigned long)count));
958                 return 0;
959         }
960
961         frame = talloc_stackframe();
962         for ( i=0; next_token_talloc(frame, &ipstr_list, &token_str,
963                                 IPSTR_LIST_SEP) && i<count; i++ ) {
964                 char *s = token_str;
965                 char *p = strrchr(token_str, ':');
966
967                 if (p) {
968                         *p = 0;
969                         (*ip_list)[i].port = atoi(p+1);
970                 }
971
972                 /* convert single token to ip address */
973                 if (token_str[0] == '[') {
974                         /* IPv6 address. */
975                         s++;
976                         p = strchr(token_str, ']');
977                         if (!p) {
978                                 continue;
979                         }
980                         *p = '\0';
981                 }
982                 if (!interpret_string_addr(&(*ip_list)[i].ss,
983                                         s,
984                                         AI_NUMERICHOST)) {
985                         continue;
986                 }
987         }
988         TALLOC_FREE(frame);
989         return count;
990 }
991
992 /**
993  * Safely free ip string list
994  *
995  * @param ipstr_list ip string list to be freed
996  **/
997
998 void ipstr_list_free(char* ipstr_list)
999 {
1000         SAFE_FREE(ipstr_list);
1001 }
1002
1003 /* read a SMB_BIG_UINT from a string */
1004 uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1005 {
1006
1007         uint64_t val = (uint64_t)-1;
1008         const char *p = nptr;
1009
1010         if (!p) {
1011                 if (entptr) {
1012                         *entptr = p;
1013                 }
1014                 return val;
1015         }
1016
1017         while (*p && isspace(*p))
1018                 p++;
1019
1020         sscanf(p,"%"PRIu64,&val);
1021         if (entptr) {
1022                 while (*p && isdigit(*p))
1023                         p++;
1024                 *entptr = p;
1025         }
1026
1027         return val;
1028 }
1029
1030 /* Convert a size specification to a count of bytes. We accept the following
1031  * suffixes:
1032  *          bytes if there is no suffix
1033  *      kK  kibibytes
1034  *      mM  mebibytes
1035  *      gG  gibibytes
1036  *      tT  tibibytes
1037  *      pP  whatever the ISO name for petabytes is
1038  *
1039  *  Returns 0 if the string can't be converted.
1040  */
1041 uint64_t conv_str_size(const char * str)
1042 {
1043         uint64_t lval_orig;
1044         uint64_t lval;
1045         char * end;
1046
1047         if (str == NULL || *str == '\0') {
1048                 return 0;
1049         }
1050
1051         lval = strtoull(str, &end, 10 /* base */);
1052
1053         if (end == NULL || end == str) {
1054                 return 0;
1055         }
1056
1057         if (*end == '\0') {
1058                 return lval;
1059         }
1060
1061         lval_orig = lval;
1062
1063         if (strwicmp(end, "K") == 0) {
1064                 lval *= 1024ULL;
1065         } else if (strwicmp(end, "M") == 0) {
1066                 lval *= (1024ULL * 1024ULL);
1067         } else if (strwicmp(end, "G") == 0) {
1068                 lval *= (1024ULL * 1024ULL *
1069                          1024ULL);
1070         } else if (strwicmp(end, "T") == 0) {
1071                 lval *= (1024ULL * 1024ULL *
1072                          1024ULL * 1024ULL);
1073         } else if (strwicmp(end, "P") == 0) {
1074                 lval *= (1024ULL * 1024ULL *
1075                          1024ULL * 1024ULL *
1076                          1024ULL);
1077         } else {
1078                 return 0;
1079         }
1080
1081         return lval;
1082 }
1083
1084 /* Append an sprintf'ed string. Double buffer size on demand. Usable without
1085  * error checking in between. The indiation that something weird happened is
1086  * string==NULL */
1087
1088 void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
1089                     size_t *bufsize, const char *fmt, ...)
1090 {
1091         va_list ap;
1092         char *newstr;
1093         int ret;
1094         bool increased;
1095
1096         /* len<0 is an internal marker that something failed */
1097         if (*len < 0)
1098                 goto error;
1099
1100         if (*string == NULL) {
1101                 if (*bufsize == 0)
1102                         *bufsize = 128;
1103
1104                 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
1105                 if (*string == NULL)
1106                         goto error;
1107         }
1108
1109         va_start(ap, fmt);
1110         ret = vasprintf(&newstr, fmt, ap);
1111         va_end(ap);
1112
1113         if (ret < 0)
1114                 goto error;
1115
1116         increased = false;
1117
1118         while ((*len)+ret >= *bufsize) {
1119                 increased = true;
1120                 *bufsize *= 2;
1121                 if (*bufsize >= (1024*1024*256))
1122                         goto error;
1123         }
1124
1125         if (increased) {
1126                 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
1127                                                *bufsize);
1128                 if (*string == NULL) {
1129                         goto error;
1130                 }
1131         }
1132
1133         StrnCpy((*string)+(*len), newstr, ret);
1134         (*len) += ret;
1135         free(newstr);
1136         return;
1137
1138  error:
1139         *len = -1;
1140         *string = NULL;
1141 }
1142
1143 /*
1144  * asprintf into a string and strupper_m it after that.
1145  */
1146
1147 int asprintf_strupper_m(char **strp, const char *fmt, ...)
1148 {
1149         va_list ap;
1150         char *result;
1151         int ret;
1152
1153         va_start(ap, fmt);
1154         ret = vasprintf(&result, fmt, ap);
1155         va_end(ap);
1156
1157         if (ret == -1)
1158                 return -1;
1159
1160         strupper_m(result);
1161         *strp = result;
1162         return ret;
1163 }
1164
1165 char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
1166 {
1167         va_list ap;
1168         char *ret;
1169
1170         va_start(ap, fmt);
1171         ret = talloc_vasprintf(t, fmt, ap);
1172         va_end(ap);
1173
1174         if (ret == NULL) {
1175                 return NULL;
1176         }
1177         strupper_m(ret);
1178         return ret;
1179 }
1180
1181 char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
1182 {
1183         va_list ap;
1184         char *ret;
1185
1186         va_start(ap, fmt);
1187         ret = talloc_vasprintf(t, fmt, ap);
1188         va_end(ap);
1189
1190         if (ret == NULL) {
1191                 return NULL;
1192         }
1193         strlower_m(ret);
1194         return ret;
1195 }
1196
1197
1198 /*
1199    Returns the substring from src between the first occurrence of
1200    the char "front" and the first occurence of the char "back".
1201    Mallocs the return string which must be freed.  Not for use
1202    with wide character strings.
1203 */
1204 char *sstring_sub(const char *src, char front, char back)
1205 {
1206         char *temp1, *temp2, *temp3;
1207         ptrdiff_t len;
1208
1209         temp1 = strchr(src, front);
1210         if (temp1 == NULL) return NULL;
1211         temp2 = strchr(src, back);
1212         if (temp2 == NULL) return NULL;
1213         len = temp2 - temp1;
1214         if (len <= 0) return NULL;
1215         temp3 = (char*)SMB_MALLOC(len);
1216         if (temp3 == NULL) {
1217                 DEBUG(1,("Malloc failure in sstring_sub\n"));
1218                 return NULL;
1219         }
1220         memcpy(temp3, temp1+1, len-1);
1221         temp3[len-1] = '\0';
1222         return temp3;
1223 }
1224
1225 /********************************************************************
1226  Check a string for any occurrences of a specified list of invalid
1227  characters.
1228 ********************************************************************/
1229
1230 bool validate_net_name( const char *name,
1231                 const char *invalid_chars,
1232                 int max_len)
1233 {
1234         int i;
1235
1236         if (!name) {
1237                 return false;
1238         }
1239
1240         for ( i=0; i<max_len && name[i]; i++ ) {
1241                 /* fail if strchr_m() finds one of the invalid characters */
1242                 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
1243                         return false;
1244                 }
1245         }
1246
1247         return true;
1248 }
1249
1250
1251 /*******************************************************************
1252  Add a shell escape character '\' to any character not in a known list
1253  of characters. UNIX charset format.
1254 *******************************************************************/
1255
1256 #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
1257 #define INSIDE_DQUOTE_LIST "$`\n\"\\"
1258
1259 char *escape_shell_string(const char *src)
1260 {
1261         size_t srclen = strlen(src);
1262         char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
1263         char *dest = ret;
1264         bool in_s_quote = false;
1265         bool in_d_quote = false;
1266         bool next_escaped = false;
1267
1268         if (!ret) {
1269                 return NULL;
1270         }
1271
1272         while (*src) {
1273                 size_t c_size;
1274                 codepoint_t c = next_codepoint(src, &c_size);
1275
1276                 if (c == INVALID_CODEPOINT) {
1277                         SAFE_FREE(ret);
1278                         return NULL;
1279                 }
1280
1281                 if (c_size > 1) {
1282                         memcpy(dest, src, c_size);
1283                         src += c_size;
1284                         dest += c_size;
1285                         next_escaped = false;
1286                         continue;
1287                 }
1288
1289                 /*
1290                  * Deal with backslash escaped state.
1291                  * This only lasts for one character.
1292                  */
1293
1294                 if (next_escaped) {
1295                         *dest++ = *src++;
1296                         next_escaped = false;
1297                         continue;
1298                 }
1299
1300                 /*
1301                  * Deal with single quote state. The
1302                  * only thing we care about is exiting
1303                  * this state.
1304                  */
1305
1306                 if (in_s_quote) {
1307                         if (*src == '\'') {
1308                                 in_s_quote = false;
1309                         }
1310                         *dest++ = *src++;
1311                         continue;
1312                 }
1313
1314                 /*
1315                  * Deal with double quote state. The most
1316                  * complex state. We must cope with \, meaning
1317                  * possibly escape next char (depending what it
1318                  * is), ", meaning exit this state, and possibly
1319                  * add an \ escape to any unprotected character
1320                  * (listed in INSIDE_DQUOTE_LIST).
1321                  */
1322
1323                 if (in_d_quote) {
1324                         if (*src == '\\') {
1325                                 /*
1326                                  * Next character might be escaped.
1327                                  * We have to peek. Inside double
1328                                  * quotes only INSIDE_DQUOTE_LIST
1329                                  * characters are escaped by a \.
1330                                  */
1331
1332                                 char nextchar;
1333
1334                                 c = next_codepoint(&src[1], &c_size);
1335                                 if (c == INVALID_CODEPOINT) {
1336                                         SAFE_FREE(ret);
1337                                         return NULL;
1338                                 }
1339                                 if (c_size > 1) {
1340                                         /*
1341                                          * Don't escape the next char.
1342                                          * Just copy the \.
1343                                          */
1344                                         *dest++ = *src++;
1345                                         continue;
1346                                 }
1347
1348                                 nextchar = src[1];
1349
1350                                 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
1351                                                         (int)nextchar)) {
1352                                         next_escaped = true;
1353                                 }
1354                                 *dest++ = *src++;
1355                                 continue;
1356                         }
1357
1358                         if (*src == '\"') {
1359                                 /* Exit double quote state. */
1360                                 in_d_quote = false;
1361                                 *dest++ = *src++;
1362                                 continue;
1363                         }
1364
1365                         /*
1366                          * We know the character isn't \ or ",
1367                          * so escape it if it's any of the other
1368                          * possible unprotected characters.
1369                          */
1370
1371                         if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
1372                                 *dest++ = '\\';
1373                         }
1374                         *dest++ = *src++;
1375                         continue;
1376                 }
1377
1378                 /*
1379                  * From here to the end of the loop we're
1380                  * not in the single or double quote state.
1381                  */
1382
1383                 if (*src == '\\') {
1384                         /* Next character must be escaped. */
1385                         next_escaped = true;
1386                         *dest++ = *src++;
1387                         continue;
1388                 }
1389
1390                 if (*src == '\'') {
1391                         /* Go into single quote state. */
1392                         in_s_quote = true;
1393                         *dest++ = *src++;
1394                         continue;
1395                 }
1396
1397                 if (*src == '\"') {
1398                         /* Go into double quote state. */
1399                         in_d_quote = true;
1400                         *dest++ = *src++;
1401                         continue;
1402                 }
1403
1404                 /* Check if we need to escape the character. */
1405
1406                 if (!strchr(INCLUDE_LIST, (int)*src)) {
1407                         *dest++ = '\\';
1408                 }
1409                 *dest++ = *src++;
1410         }
1411         *dest++ = '\0';
1412         return ret;
1413 }
1414
1415 /***************************************************
1416  str_list_make, v3 version. The v4 version does not
1417  look at quoted strings with embedded blanks, so
1418  do NOT merge this function please!
1419 ***************************************************/
1420
1421 #define S_LIST_ABS 16 /* List Allocation Block Size */
1422
1423 char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
1424         const char *sep)
1425 {
1426         char **list;
1427         const char *str;
1428         char *s, *tok;
1429         int num, lsize;
1430
1431         if (!string || !*string)
1432                 return NULL;
1433
1434         list = TALLOC_ARRAY(mem_ctx, char *, S_LIST_ABS+1);
1435         if (list == NULL) {
1436                 return NULL;
1437         }
1438         lsize = S_LIST_ABS;
1439
1440         s = talloc_strdup(list, string);
1441         if (s == NULL) {
1442                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1443                 TALLOC_FREE(list);
1444                 return NULL;
1445         }
1446         if (!sep) sep = LIST_SEP;
1447
1448         num = 0;
1449         str = s;
1450
1451         while (next_token_talloc(list, &str, &tok, sep)) {
1452
1453                 if (num == lsize) {
1454                         char **tmp;
1455
1456                         lsize += S_LIST_ABS;
1457
1458                         tmp = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *,
1459                                                    lsize + 1);
1460                         if (tmp == NULL) {
1461                                 DEBUG(0,("str_list_make: "
1462                                         "Unable to allocate memory"));
1463                                 TALLOC_FREE(list);
1464                                 return NULL;
1465                         }
1466
1467                         list = tmp;
1468
1469                         memset (&list[num], 0,
1470                                 ((sizeof(char**)) * (S_LIST_ABS +1)));
1471                 }
1472
1473                 list[num] = tok;
1474                 num += 1;
1475         }
1476
1477         list[num] = NULL;
1478
1479         TALLOC_FREE(s);
1480         return list;
1481 }
1482
1483 char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
1484 {
1485         fstring tmp;
1486
1487         alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
1488         return talloc_strdup(mem_ctx, tmp);
1489 }