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