r13336: Doh! We actually never optimized for the ascii case.
[samba.git] / source / lib / util_str.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    
5    Copyright (C) Andrew Tridgell 1992-2001
6    Copyright (C) Simo Sorce      2001-2002
7    Copyright (C) Martin Pool     2003
8    Copyright (C) James Peach     2005
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26 #include "system/iconv.h"
27 #include "smb.h"
28 #include "pstring.h"
29 #include "lib/ldb/include/ldb.h"
30
31 /**
32  * @file
33  * @brief String utilities.
34  **/
35
36 /**
37  * Get the next token from a string, return False if none found.
38  * Handles double-quotes.
39  * 
40  * Based on a routine by GJC@VILLAGE.COM. 
41  * Extensively modified by Andrew.Tridgell@anu.edu.au
42  **/
43 BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
44 {
45         const char *s;
46         BOOL quoted;
47         size_t len=1;
48
49         if (!ptr)
50                 return(False);
51
52         s = *ptr;
53
54         /* default to simple separators */
55         if (!sep)
56                 sep = " \t\n\r";
57
58         /* find the first non sep char */
59         while (*s && strchr_m(sep,*s))
60                 s++;
61         
62         /* nothing left? */
63         if (! *s)
64                 return(False);
65         
66         /* copy over the token */
67         for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
68                 if (*s == '\"') {
69                         quoted = !quoted;
70                 } else {
71                         len++;
72                         *buff++ = *s;
73                 }
74         }
75         
76         *ptr = (*s) ? s+1 : s;  
77         *buff = 0;
78         
79         return(True);
80 }
81
82 /**
83  Case insensitive string compararison
84 **/
85 int strcasecmp_m(const char *s1, const char *s2)
86 {
87         codepoint_t c1=0, c2=0;
88         size_t size1, size2;
89
90         while (*s1 && *s2) {
91                 c1 = next_codepoint(s1, &size1);
92                 c2 = next_codepoint(s2, &size2);
93
94                 s1 += size1;
95                 s2 += size2;
96
97                 if (c1 == c2) {
98                         continue;
99                 }
100
101                 if (c1 == INVALID_CODEPOINT ||
102                     c2 == INVALID_CODEPOINT) {
103                         /* what else can we do?? */
104                         return c1 - c2;
105                 }
106
107                 if (toupper_w(c1) != toupper_w(c2)) {
108                         return c1 - c2;
109                 }
110         }
111
112         return *s1 - *s2;
113 }
114
115 /**
116  * Compare 2 strings.
117  *
118  * @note The comparison is case-insensitive.
119  **/
120 BOOL strequal(const char *s1, const char *s2)
121 {
122         if (s1 == s2)
123                 return(True);
124         if (!s1 || !s2)
125                 return(False);
126   
127         return strcasecmp_m(s1,s2) == 0;
128 }
129
130 /**
131  Compare 2 strings (case sensitive).
132 **/
133 BOOL strcsequal(const char *s1,const char *s2)
134 {
135         if (s1 == s2)
136                 return(True);
137         if (!s1 || !s2)
138                 return(False);
139         
140         return strcmp(s1,s2) == 0;
141 }
142
143
144 /**
145 Do a case-insensitive, whitespace-ignoring string compare.
146 **/
147 int strwicmp(const char *psz1, const char *psz2)
148 {
149         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
150         /* appropriate value. */
151         if (psz1 == psz2)
152                 return (0);
153         else if (psz1 == NULL)
154                 return (-1);
155         else if (psz2 == NULL)
156                 return (1);
157
158         /* sync the strings on first non-whitespace */
159         while (1) {
160                 while (isspace((int)*psz1))
161                         psz1++;
162                 while (isspace((int)*psz2))
163                         psz2++;
164                 if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2) 
165                     || *psz1 == '\0'
166                     || *psz2 == '\0')
167                         break;
168                 psz1++;
169                 psz2++;
170         }
171         return (*psz1 - *psz2);
172 }
173
174 /**
175  String replace.
176  NOTE: oldc and newc must be 7 bit characters
177 **/
178 void string_replace(char *s, char oldc, char newc)
179 {
180         while (*s) {
181                 size_t size;
182                 codepoint_t c = next_codepoint(s, &size);
183                 if (c == oldc) {
184                         *s = newc;
185                 }
186                 s += size;
187         }
188 }
189
190 /**
191  Trim the specified elements off the front and back of a string.
192 **/
193 BOOL trim_string(char *s,const char *front,const char *back)
194 {
195         BOOL ret = False;
196         size_t front_len;
197         size_t back_len;
198         size_t len;
199
200         /* Ignore null or empty strings. */
201         if (!s || (s[0] == '\0'))
202                 return False;
203
204         front_len       = front? strlen(front) : 0;
205         back_len        = back? strlen(back) : 0;
206
207         len = strlen(s);
208
209         if (front_len) {
210                 while (len && strncmp(s, front, front_len)==0) {
211                         /* Must use memmove here as src & dest can
212                          * easily overlap. Found by valgrind. JRA. */
213                         memmove(s, s+front_len, (len-front_len)+1);
214                         len -= front_len;
215                         ret=True;
216                 }
217         }
218         
219         if (back_len) {
220                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
221                         s[len-back_len]='\0';
222                         len -= back_len;
223                         ret=True;
224                 }
225         }
226         return ret;
227 }
228
229 /**
230  Find the number of 'c' chars in a string
231 **/
232 size_t count_chars(const char *s, char c)
233 {
234         size_t count = 0;
235
236         while (*s) {
237                 size_t size;
238                 codepoint_t c2 = next_codepoint(s, &size);
239                 if (c2 == c) count++;
240                 s += size;
241         }
242
243         return count;
244 }
245
246 /**
247  Safe string copy into a known length string. maxlength does not
248  include the terminating zero.
249 **/
250 char *safe_strcpy(char *dest,const char *src, size_t maxlength)
251 {
252         size_t len;
253
254         if (!dest) {
255                 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
256                 return NULL;
257         }
258
259 #ifdef DEVELOPER
260         /* We intentionally write out at the extremity of the destination
261          * string.  If the destination is too short (e.g. pstrcpy into mallocd
262          * or fstring) then this should cause an error under a memory
263          * checker. */
264         dest[maxlength] = '\0';
265         if (PTR_DIFF(&len, dest) > 0) {  /* check if destination is on the stack, ok if so */
266                 log_suspicious_usage("safe_strcpy", src);
267         }
268 #endif
269
270         if (!src) {
271                 *dest = 0;
272                 return dest;
273         }  
274
275         len = strlen(src);
276
277         if (len > maxlength) {
278                 DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
279                          (uint_t)(len-maxlength), (unsigned)len, (unsigned)maxlength, src));
280                 len = maxlength;
281         }
282       
283         memmove(dest, src, len);
284         dest[len] = 0;
285         return dest;
286 }  
287
288 /**
289  Safe string cat into a string. maxlength does not
290  include the terminating zero.
291 **/
292 char *safe_strcat(char *dest, const char *src, size_t maxlength)
293 {
294         size_t src_len, dest_len;
295
296         if (!dest) {
297                 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
298                 return NULL;
299         }
300
301         if (!src)
302                 return dest;
303         
304 #ifdef DEVELOPER
305         if (PTR_DIFF(&src_len, dest) > 0) {  /* check if destination is on the stack, ok if so */
306                 log_suspicious_usage("safe_strcat", src);
307         }
308 #endif
309         src_len = strlen(src);
310         dest_len = strlen(dest);
311
312         if (src_len + dest_len > maxlength) {
313                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
314                          (int)(src_len + dest_len - maxlength), src));
315                 if (maxlength > dest_len) {
316                         memcpy(&dest[dest_len], src, maxlength - dest_len);
317                 }
318                 dest[maxlength] = 0;
319                 return NULL;
320         }
321         
322         memcpy(&dest[dest_len], src, src_len);
323         dest[dest_len + src_len] = 0;
324         return dest;
325 }
326
327 /**
328  Paranoid strcpy into a buffer of given length (includes terminating
329  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
330  and replaces with '_'. Deliberately does *NOT* check for multibyte
331  characters. Don't change it !
332 **/
333
334 char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
335 {
336         size_t len, i;
337
338         if (maxlength == 0) {
339                 /* can't fit any bytes at all! */
340                 return NULL;
341         }
342
343         if (!dest) {
344                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
345                 return NULL;
346         }
347
348         if (!src) {
349                 *dest = 0;
350                 return dest;
351         }  
352
353         len = strlen(src);
354         if (len >= maxlength)
355                 len = maxlength - 1;
356
357         if (!other_safe_chars)
358                 other_safe_chars = "";
359
360         for(i = 0; i < len; i++) {
361                 int val = (src[i] & 0xff);
362                 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
363                         dest[i] = src[i];
364                 else
365                         dest[i] = '_';
366         }
367
368         dest[i] = '\0';
369
370         return dest;
371 }
372
373 /**
374  Like strncpy but always null terminates. Make sure there is room!
375  The variable n should always be one less than the available size.
376 **/
377
378 char *StrnCpy(char *dest,const char *src,size_t n)
379 {
380         char *d = dest;
381         if (!dest)
382                 return(NULL);
383         if (!src) {
384                 *dest = 0;
385                 return(dest);
386         }
387         while (n-- && (*d++ = *src++))
388                 ;
389         *d = 0;
390         return(dest);
391 }
392
393
394 /**
395  Routine to get hex characters and turn them into a 16 byte array.
396  the array can be variable length, and any non-hex-numeric
397  characters are skipped.  "0xnn" or "0Xnn" is specially catered
398  for.
399
400  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
401
402
403 **/
404 size_t strhex_to_str(char *p, size_t len, const char *strhex)
405 {
406         size_t i;
407         size_t num_chars = 0;
408         uint8_t   lonybble, hinybble;
409         const char     *hexchars = "0123456789ABCDEF";
410         char           *p1 = NULL, *p2 = NULL;
411
412         for (i = 0; i < len && strhex[i] != 0; i++) {
413                 if (strncasecmp(hexchars, "0x", 2) == 0) {
414                         i++; /* skip two chars */
415                         continue;
416                 }
417
418                 if (!(p1 = strchr_m(hexchars, toupper((unsigned char)strhex[i]))))
419                         break;
420
421                 i++; /* next hex digit */
422
423                 if (!(p2 = strchr_m(hexchars, toupper((unsigned char)strhex[i]))))
424                         break;
425
426                 /* get the two nybbles */
427                 hinybble = PTR_DIFF(p1, hexchars);
428                 lonybble = PTR_DIFF(p2, hexchars);
429
430                 p[num_chars] = (hinybble << 4) | lonybble;
431                 num_chars++;
432
433                 p1 = NULL;
434                 p2 = NULL;
435         }
436         return num_chars;
437 }
438
439 DATA_BLOB strhex_to_data_blob(const char *strhex) 
440 {
441         DATA_BLOB ret_blob = data_blob(NULL, strlen(strhex)/2+1);
442
443         ret_blob.length = strhex_to_str((char *)ret_blob.data,  
444                                         strlen(strhex), 
445                                         strhex);
446
447         return ret_blob;
448 }
449
450
451 /**
452  * Routine to print a buffer as HEX digits, into an allocated string.
453  */
454 void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
455 {
456         int i;
457         char *hex_buffer;
458
459         *out_hex_buffer = smb_xmalloc((len*2)+1);
460         hex_buffer = *out_hex_buffer;
461
462         for (i = 0; i < len; i++)
463                 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
464 }
465
466 /**
467  Check if a string is part of a list.
468 **/
469 BOOL in_list(const char *s, const char *list, BOOL casesensitive)
470 {
471         pstring tok;
472         const char *p=list;
473
474         if (!list)
475                 return(False);
476
477         while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
478                 if (casesensitive) {
479                         if (strcmp(tok,s) == 0)
480                                 return(True);
481                 } else {
482                         if (strcasecmp_m(tok,s) == 0)
483                                 return(True);
484                 }
485         }
486         return(False);
487 }
488
489 /**
490  Set a string value, allocing the space for the string
491 **/
492 static BOOL string_init(char **dest,const char *src)
493 {
494         if (!src) src = "";
495
496         (*dest) = strdup(src);
497         if ((*dest) == NULL) {
498                 DEBUG(0,("Out of memory in string_init\n"));
499                 return False;
500         }
501         return True;
502 }
503
504 /**
505  Free a string value.
506 **/
507 void string_free(char **s)
508 {
509         if (s) SAFE_FREE(*s);
510 }
511
512 /**
513  Set a string value, deallocating any existing space, and allocing the space
514  for the string
515 **/
516 BOOL string_set(char **dest, const char *src)
517 {
518         string_free(dest);
519         return string_init(dest,src);
520 }
521
522 /**
523  Substitute a string for a pattern in another string. Make sure there is 
524  enough room!
525
526  This routine looks for pattern in s and replaces it with 
527  insert. It may do multiple replacements.
528
529  Any of " ; ' $ or ` in the insert string are replaced with _
530  if len==0 then the string cannot be extended. This is different from the old
531  use of len==0 which was for no length checks to be done.
532 **/
533
534 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
535 {
536         char *p;
537         ssize_t ls,lp,li, i;
538
539         if (!insert || !pattern || !*pattern || !s)
540                 return;
541
542         ls = (ssize_t)strlen(s);
543         lp = (ssize_t)strlen(pattern);
544         li = (ssize_t)strlen(insert);
545
546         if (len == 0)
547                 len = ls + 1; /* len is number of *bytes* */
548
549         while (lp <= ls && (p = strstr(s,pattern))) {
550                 if (ls + (li-lp) >= len) {
551                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
552                                  (int)(ls + (li-lp) - len),
553                                  pattern, (int)len));
554                         break;
555                 }
556                 if (li != lp) {
557                         memmove(p+li,p+lp,strlen(p+lp)+1);
558                 }
559                 for (i=0;i<li;i++) {
560                         switch (insert[i]) {
561                         case '`':
562                         case '"':
563                         case '\'':
564                         case ';':
565                         case '$':
566                         case '%':
567                         case '\r':
568                         case '\n':
569                                 p[i] = '_';
570                                 break;
571                         default:
572                                 p[i] = insert[i];
573                         }
574                 }
575                 s = p + li;
576                 ls += (li-lp);
577         }
578 }
579
580
581 /**
582  Similar to string_sub() but allows for any character to be substituted. 
583  Use with caution!
584  if len==0 then the string cannot be extended. This is different from the old
585  use of len==0 which was for no length checks to be done.
586 **/
587
588 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
589 {
590         char *p;
591         ssize_t ls,lp,li;
592
593         if (!insert || !pattern || !s)
594                 return;
595
596         ls = (ssize_t)strlen(s);
597         lp = (ssize_t)strlen(pattern);
598         li = (ssize_t)strlen(insert);
599
600         if (!*pattern)
601                 return;
602         
603         if (len == 0)
604                 len = ls + 1; /* len is number of *bytes* */
605         
606         while (lp <= ls && (p = strstr(s,pattern))) {
607                 if (ls + (li-lp) >= len) {
608                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
609                                  (int)(ls + (li-lp) - len),
610                                  pattern, (int)len));
611                         break;
612                 }
613                 if (li != lp) {
614                         memmove(p+li,p+lp,strlen(p+lp)+1);
615                 }
616                 memcpy(p, insert, li);
617                 s = p + li;
618                 ls += (li-lp);
619         }
620 }
621
622
623 /**
624  Strchr and strrchr_m are a bit complex on general multi-byte strings. 
625 **/
626 char *strchr_m(const char *s, char c)
627 {
628         /* characters below 0x3F are guaranteed to not appear in
629            non-initial position in multi-byte charsets */
630         if ((c & 0xC0) == 0) {
631                 return strchr(s, c);
632         }
633
634         while (*s) {
635                 size_t size;
636                 codepoint_t c2 = next_codepoint(s, &size);
637                 if (c2 == c) {
638                         return discard_const(s);
639                 }
640                 s += size;
641         }
642
643         return NULL;
644 }
645
646 char *strrchr_m(const char *s, char c)
647 {
648         char *ret = NULL;
649
650         /* characters below 0x3F are guaranteed to not appear in
651            non-initial position in multi-byte charsets */
652         if ((c & 0xC0) == 0) {
653                 return strrchr(s, c);
654         }
655
656         while (*s) {
657                 size_t size;
658                 codepoint_t c2 = next_codepoint(s, &size);
659                 if (c2 == c) {
660                         ret = discard_const(s);
661                 }
662                 s += size;
663         }
664
665         return ret;
666 }
667
668 /*
669   return True if any (multi-byte) character is lower case
670 */
671 BOOL strhaslower(const char *string)
672 {
673         while (*string) {
674                 size_t c_size;
675                 codepoint_t s;
676                 codepoint_t t;
677
678                 s = next_codepoint(string, &c_size);
679                 string += c_size;
680
681                 t = toupper_w(s);
682
683                 if (s != t) {
684                         return True; /* that means it has lower case chars */
685                 }
686         }
687
688         return False;
689
690
691 /*
692   return True if any (multi-byte) character is upper case
693 */
694 BOOL strhasupper(const char *string)
695 {
696         while (*string) {
697                 size_t c_size;
698                 codepoint_t s;
699                 codepoint_t t;
700
701                 s = next_codepoint(string, &c_size);
702                 string += c_size;
703
704                 t = tolower_w(s);
705
706                 if (s != t) {
707                         return True; /* that means it has upper case chars */
708                 }
709         }
710
711         return False;
712
713
714 /**
715  Convert a string to lower case, allocated with talloc
716 **/
717 char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
718 {
719         size_t size=0;
720         char *dest;
721
722         /* this takes advantage of the fact that upper/lower can't
723            change the length of a character by more than 1 byte */
724         dest = talloc_size(ctx, 2*(strlen(src))+1);
725         if (dest == NULL) {
726                 return NULL;
727         }
728
729         while (*src) {
730                 size_t c_size;
731                 codepoint_t c = next_codepoint(src, &c_size);
732                 src += c_size;
733
734                 c = tolower_w(c);
735
736                 c_size = push_codepoint(dest+size, c);
737                 if (c_size == -1) {
738                         talloc_free(dest);
739                         return NULL;
740                 }
741                 size += c_size;
742         }
743
744         dest[size] = 0;
745
746         return dest;
747 }
748
749 /**
750  Convert a string to UPPER case, allocated with talloc
751 **/
752 char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
753 {
754         size_t size=0;
755         char *dest;
756         
757         if (!src) {
758                 return NULL;
759         }
760
761         /* this takes advantage of the fact that upper/lower can't
762            change the length of a character by more than 1 byte */
763         dest = talloc_size(ctx, 2*(strlen(src))+1);
764         if (dest == NULL) {
765                 return NULL;
766         }
767
768         while (*src) {
769                 size_t c_size;
770                 codepoint_t c = next_codepoint(src, &c_size);
771                 src += c_size;
772
773                 c = toupper_w(c);
774
775                 c_size = push_codepoint(dest+size, c);
776                 if (c_size == -1) {
777                         talloc_free(dest);
778                         return NULL;
779                 }
780                 size += c_size;
781         }
782
783         dest[size] = 0;
784
785         return dest;
786 }
787
788 /**
789  Convert a string to lower case.
790 **/
791 void strlower_m(char *s)
792 {
793         char *d;
794
795         /* this is quite a common operation, so we want it to be
796            fast. We optimise for the ascii case, knowing that all our
797            supported multi-byte character sets are ascii-compatible
798            (ie. they match for the first 128 chars) */
799         while (*s && !(((uint8_t)*s) & 0x80)) {
800                 *s = tolower((uint8_t)*s);
801                 s++;
802         }
803
804         if (!*s)
805                 return;
806
807         d = s;
808
809         while (*s) {
810                 size_t c_size, c_size2;
811                 codepoint_t c = next_codepoint(s, &c_size);
812                 c_size2 = push_codepoint(d, tolower_w(c));
813                 if (c_size2 > c_size) {
814                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
815                                  c, tolower_w(c), (int)c_size, (int)c_size2));
816                         smb_panic("codepoint expansion in strlower_m\n");
817                 }
818                 s += c_size;
819                 d += c_size2;
820         }
821         *d = 0;
822 }
823
824 /**
825  Convert a string to UPPER case.
826 **/
827 void strupper_m(char *s)
828 {
829         char *d;
830
831         /* this is quite a common operation, so we want it to be
832            fast. We optimise for the ascii case, knowing that all our
833            supported multi-byte character sets are ascii-compatible
834            (ie. they match for the first 128 chars) */
835         while (*s && !(((uint8_t)*s) & 0x80)) {
836                 *s = toupper((uint8_t)*s);
837                 s++;
838         }
839
840         if (!*s)
841                 return;
842
843         d = s;
844
845         while (*s) {
846                 size_t c_size, c_size2;
847                 codepoint_t c = next_codepoint(s, &c_size);
848                 c_size2 = push_codepoint(d, toupper_w(c));
849                 if (c_size2 > c_size) {
850                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
851                                  c, toupper_w(c), (int)c_size, (int)c_size2));
852                         smb_panic("codepoint expansion in strupper_m\n");
853                 }
854                 s += c_size;
855                 d += c_size2;
856         }
857         *d = 0;
858 }
859
860 /**
861  Count the number of UCS2 characters in a string. Normally this will
862  be the same as the number of bytes in a string for single byte strings,
863  but will be different for multibyte.
864 **/
865 size_t strlen_m(const char *s)
866 {
867         size_t count = 0;
868
869         if (!s) {
870                 return 0;
871         }
872
873         while (*s && !(((uint8_t)*s) & 0x80)) {
874                 s++;
875                 count++;
876         }
877
878         if (!*s) {
879                 return count;
880         }
881
882         while (*s) {
883                 size_t c_size;
884                 codepoint_t c = next_codepoint(s, &c_size);
885                 if (c < 0x10000) {
886                         count += 1;
887                 } else {
888                         count += 2;
889                 }
890                 s += c_size;
891         }
892
893         return count;
894 }
895
896 /**
897    Work out the number of multibyte chars in a string, including the NULL
898    terminator.
899 **/
900 size_t strlen_m_term(const char *s)
901 {
902         if (!s) {
903                 return 0;
904         }
905
906         return strlen_m(s) + 1;
907 }
908
909 /**
910  Unescape a URL encoded string, in place.
911 **/
912
913 void rfc1738_unescape(char *buf)
914 {
915         char *p=buf;
916
917         while ((p=strchr_m(p,'+')))
918                 *p = ' ';
919
920         p = buf;
921
922         while (p && *p && (p=strchr_m(p,'%'))) {
923                 int c1 = p[1];
924                 int c2 = p[2];
925
926                 if (c1 >= '0' && c1 <= '9')
927                         c1 = c1 - '0';
928                 else if (c1 >= 'A' && c1 <= 'F')
929                         c1 = 10 + c1 - 'A';
930                 else if (c1 >= 'a' && c1 <= 'f')
931                         c1 = 10 + c1 - 'a';
932                 else {p++; continue;}
933
934                 if (c2 >= '0' && c2 <= '9')
935                         c2 = c2 - '0';
936                 else if (c2 >= 'A' && c2 <= 'F')
937                         c2 = 10 + c2 - 'A';
938                 else if (c2 >= 'a' && c2 <= 'f')
939                         c2 = 10 + c2 - 'a';
940                 else {p++; continue;}
941                         
942                 *p = (c1<<4) | c2;
943
944                 memmove(p+1, p+3, strlen(p+3)+1);
945                 p++;
946         }
947 }
948
949 /**
950  * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
951  **/
952 DATA_BLOB base64_decode_data_blob(TALLOC_CTX *mem_ctx, const char *s)
953 {
954         DATA_BLOB ret = data_blob_talloc(mem_ctx, s, strlen(s)+1);
955         ret.length = ldb_base64_decode((char *)ret.data);
956         return ret;
957 }
958
959 /**
960  * Decode a base64 string in-place - wrapper for the above
961  **/
962 void base64_decode_inplace(char *s)
963 {
964         ldb_base64_decode(s);
965 }
966
967 /**
968  * Encode a base64 string into a talloc()ed string caller to free.
969  **/
970 char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data)
971 {
972         return ldb_base64_encode(mem_ctx, (const char *)data.data, data.length);
973 }
974
975 #ifdef VALGRIND
976 size_t valgrind_strlen(const char *s)
977 {
978         size_t count;
979         for(count = 0; *s++; count++)
980                 ;
981         return count;
982 }
983 #endif
984
985
986 /*
987   format a string into length-prefixed dotted domain format, as used in NBT
988   and in some ADS structures
989 */
990 const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s)
991 {
992         char *ret;
993         int i;
994         if (!s || !*s) {
995                 return talloc_strdup(mem_ctx, "");
996         }
997         ret = talloc_size(mem_ctx, strlen(s)+2);
998         if (!ret) {
999                 return ret;
1000         }
1001         
1002         memcpy(ret+1, s, strlen(s)+1);
1003         ret[0] = '.';
1004
1005         for (i=0;ret[i];i++) {
1006                 if (ret[i] == '.') {
1007                         char *p = strchr(ret+i+1, '.');
1008                         if (p) {
1009                                 ret[i] = p-(ret+i+1);
1010                         } else {
1011                                 ret[i] = strlen(ret+i+1);
1012                         }
1013                 }
1014         }
1015
1016         return ret;
1017 }
1018
1019 BOOL add_string_to_array(TALLOC_CTX *mem_ctx,
1020                          const char *str, const char ***strings, int *num)
1021 {
1022         char *dup_str = talloc_strdup(mem_ctx, str);
1023
1024         *strings = talloc_realloc(mem_ctx,
1025                                     *strings,
1026                                     const char *, ((*num)+1));
1027
1028         if ((*strings == NULL) || (dup_str == NULL))
1029                 return False;
1030
1031         (*strings)[*num] = dup_str;
1032         *num += 1;
1033
1034         return True;
1035 }
1036
1037
1038
1039 /*
1040   varient of strcmp() that handles NULL ptrs
1041 */
1042 int strcmp_safe(const char *s1, const char *s2)
1043 {
1044         if (s1 == s2) {
1045                 return 0;
1046         }
1047         if (s1 == NULL || s2 == NULL) {
1048                 return s1?-1:1;
1049         }
1050         return strcmp(s1, s2);
1051 }
1052
1053
1054 /*******************************************************************
1055 return the number of bytes occupied by a buffer in ASCII format
1056 the result includes the null termination
1057 limited by 'n' bytes
1058 ********************************************************************/
1059 size_t ascii_len_n(const char *src, size_t n)
1060 {
1061         size_t len;
1062
1063         len = strnlen(src, n);
1064         if (len+1 <= n) {
1065                 len += 1;
1066         }
1067
1068         return len;
1069 }
1070
1071
1072 /*******************************************************************
1073  Return a string representing a CIFS attribute for a file.
1074 ********************************************************************/
1075 char *attrib_string(TALLOC_CTX *mem_ctx, uint32_t attrib)
1076 {
1077         int i, len;
1078         const struct {
1079                 char c;
1080                 uint16_t attr;
1081         } attr_strs[] = {
1082                 {'V', FILE_ATTRIBUTE_VOLUME},
1083                 {'D', FILE_ATTRIBUTE_DIRECTORY},
1084                 {'A', FILE_ATTRIBUTE_ARCHIVE},
1085                 {'H', FILE_ATTRIBUTE_HIDDEN},
1086                 {'S', FILE_ATTRIBUTE_SYSTEM},
1087                 {'N', FILE_ATTRIBUTE_NORMAL},
1088                 {'R', FILE_ATTRIBUTE_READONLY},
1089                 {'d', FILE_ATTRIBUTE_DEVICE},
1090                 {'t', FILE_ATTRIBUTE_TEMPORARY},
1091                 {'s', FILE_ATTRIBUTE_SPARSE},
1092                 {'r', FILE_ATTRIBUTE_REPARSE_POINT},
1093                 {'c', FILE_ATTRIBUTE_COMPRESSED},
1094                 {'o', FILE_ATTRIBUTE_OFFLINE},
1095                 {'n', FILE_ATTRIBUTE_NONINDEXED},
1096                 {'e', FILE_ATTRIBUTE_ENCRYPTED}
1097         };
1098         char *ret;
1099
1100         ret = talloc_size(mem_ctx, ARRAY_SIZE(attr_strs)+1);
1101         if (!ret) {
1102                 return NULL;
1103         }
1104
1105         for (len=i=0; i<ARRAY_SIZE(attr_strs); i++) {
1106                 if (attrib & attr_strs[i].attr) {
1107                         ret[len++] = attr_strs[i].c;
1108                 }
1109         }
1110
1111         ret[len] = 0;
1112
1113         return ret;
1114 }
1115
1116 /***************************************************************************
1117  Set a boolean variable from the text value stored in the passed string.
1118  Returns True in success, False if the passed string does not correctly 
1119  represent a boolean.
1120 ***************************************************************************/
1121
1122 BOOL set_boolean(const char *boolean_string, BOOL *boolean)
1123 {
1124         if (strwicmp(boolean_string, "yes") == 0 ||
1125             strwicmp(boolean_string, "true") == 0 ||
1126             strwicmp(boolean_string, "on") == 0 ||
1127             strwicmp(boolean_string, "1") == 0) {
1128                 *boolean = True;
1129                 return True;
1130         } else if (strwicmp(boolean_string, "no") == 0 ||
1131                    strwicmp(boolean_string, "false") == 0 ||
1132                    strwicmp(boolean_string, "off") == 0 ||
1133                    strwicmp(boolean_string, "0") == 0) {
1134                 *boolean = False;
1135                 return True;
1136         }
1137         return False;
1138 }
1139
1140 BOOL conv_str_bool(const char * str, BOOL * val)
1141 {
1142         char *  end = NULL;
1143         long    lval;
1144
1145         if (str == NULL || *str == '\0') {
1146                 return False;
1147         }
1148
1149         lval = strtol(str, &end, 10 /* base */);
1150         if (end == NULL || *end != '\0' || end == str) {
1151                 return set_boolean(str, val);
1152         }
1153
1154         *val = (lval) ? True : False;
1155         return True;
1156 }
1157
1158 /* Convert a size specification like 16K into an integral number of bytes. */
1159 BOOL conv_str_size(const char * str, uint64_t * val)
1160 {
1161         char *              end = NULL;
1162         unsigned long long  lval;
1163
1164         if (str == NULL || *str == '\0') {
1165                 return False;
1166         }
1167
1168         lval = strtoull(str, &end, 10 /* base */);
1169         if (end == NULL || end == str) {
1170                 return False;
1171         }
1172
1173         if (*end) {
1174                 if (strwicmp(end, "K") == 0) {
1175                         lval *= 1024ULL;
1176                 } else if (strwicmp(end, "M") == 0) {
1177                         lval *= (1024ULL * 1024ULL);
1178                 } else if (strwicmp(end, "G") == 0) {
1179                         lval *= (1024ULL * 1024ULL * 1024ULL);
1180                 } else if (strwicmp(end, "T") == 0) {
1181                         lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL);
1182                 } else if (strwicmp(end, "P") == 0) {
1183                         lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL);
1184                 } else {
1185                         return False;
1186                 }
1187         }
1188
1189         *val = (uint64_t)lval;
1190         return True;
1191 }
1192
1193 BOOL conv_str_u64(const char * str, uint64_t * val)
1194 {
1195         char *              end = NULL;
1196         unsigned long long  lval;
1197
1198         if (str == NULL || *str == '\0') {
1199                 return False;
1200         }
1201
1202         lval = strtoull(str, &end, 10 /* base */);
1203         if (end == NULL || *end != '\0' || end == str) {
1204                 return False;
1205         }
1206
1207         *val = (uint64_t)lval;
1208         return True;
1209 }