BIG patch...
[sfrench/samba-autobuild/.git] / source3 / lib / util_str.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-2001
5    Copyright (C) Simo Sorce      2001-2002
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 /****************************************************************************
25  Get the next token from a string, return False if none found.
26  Handles double-quotes. 
27  Based on a routine by GJC@VILLAGE.COM. 
28  Extensively modified by Andrew.Tridgell@anu.edu.au
29 ****************************************************************************/
30
31 BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
32 {
33         const char *s;
34         BOOL quoted;
35         size_t len=1;
36
37         if (!ptr)
38                 return(False);
39
40         s = *ptr;
41
42         /* default to simple separators */
43         if (!sep)
44                 sep = " \t\n\r";
45
46         /* find the first non sep char */
47         while (*s && strchr_m(sep,*s))
48                 s++;
49         
50         /* nothing left? */
51         if (! *s)
52                 return(False);
53         
54         /* copy over the token */
55         for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
56                 if (*s == '\"') {
57                         quoted = !quoted;
58                 } else {
59                         len++;
60                         *buff++ = *s;
61                 }
62         }
63         
64         *ptr = (*s) ? s+1 : s;  
65         *buff = 0;
66         
67         return(True);
68 }
69
70 /****************************************************************************
71 This is like next_token but is not re-entrant and "remembers" the first 
72 parameter so you can pass NULL. This is useful for user interface code
73 but beware the fact that it is not re-entrant!
74 ****************************************************************************/
75
76 static char *last_ptr=NULL;
77
78 BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
79 {
80         BOOL ret;
81         if (!ptr)
82                 ptr = (const char **)&last_ptr;
83
84         ret = next_token(ptr, buff, sep, bufsize);
85         last_ptr = *ptr;
86         return ret;     
87 }
88
89 static uint16 tmpbuf[sizeof(pstring)];
90
91 void set_first_token(char *ptr)
92 {
93         last_ptr = ptr;
94 }
95
96 /****************************************************************************
97  Convert list of tokens to array; dependent on above routine.
98  Uses last_ptr from above - bit of a hack.
99 ****************************************************************************/
100
101 char **toktocliplist(int *ctok, const char *sep)
102 {
103         char *s=last_ptr;
104         int ictok=0;
105         char **ret, **iret;
106
107         if (!sep)
108                 sep = " \t\n\r";
109
110         while(*s && strchr_m(sep,*s))
111                 s++;
112
113         /* nothing left? */
114         if (!*s)
115                 return(NULL);
116
117         do {
118                 ictok++;
119                 while(*s && (!strchr_m(sep,*s)))
120                         s++;
121                 while(*s && strchr_m(sep,*s))
122                         *s++=0;
123         } while(*s);
124         
125         *ctok=ictok;
126         s=last_ptr;
127         
128         if (!(ret=iret=malloc(ictok*sizeof(char *))))
129                 return NULL;
130         
131         while(ictok--) {    
132                 *iret++=s;
133                 while(*s++)
134                         ;
135                 while(!*s)
136                         s++;
137         }
138
139         return ret;
140 }
141
142 /*******************************************************************
143  Case insensitive string compararison.
144 ********************************************************************/
145
146 int StrCaseCmp(const char *s, const char *t)
147 {
148         pstring buf1, buf2;
149         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
150         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
151         return strcmp(buf1,buf2);
152 }
153
154 /*******************************************************************
155  Case insensitive string compararison, length limited.
156 ********************************************************************/
157
158 int StrnCaseCmp(const char *s, const char *t, size_t n)
159 {
160         pstring buf1, buf2;
161         unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
162         unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
163         return strncmp(buf1,buf2,n);
164 }
165
166 /*******************************************************************
167  Compare 2 strings.
168 ********************************************************************/
169
170 BOOL strequal(const char *s1, const char *s2)
171 {
172         if (s1 == s2)
173                 return(True);
174         if (!s1 || !s2)
175                 return(False);
176   
177         return(StrCaseCmp(s1,s2)==0);
178 }
179
180 /*******************************************************************
181  Compare 2 strings up to and including the nth char.
182 ******************************************************************/
183
184 BOOL strnequal(const char *s1,const char *s2,size_t n)
185 {
186   if (s1 == s2)
187           return(True);
188   if (!s1 || !s2 || !n)
189           return(False);
190   
191   return(StrnCaseCmp(s1,s2,n)==0);
192 }
193
194 /*******************************************************************
195  Compare 2 strings (case sensitive).
196 ********************************************************************/
197
198 BOOL strcsequal(const char *s1,const char *s2)
199 {
200   if (s1 == s2)
201           return(True);
202   if (!s1 || !s2)
203           return(False);
204   
205   return(strcmp(s1,s2)==0);
206 }
207
208 /***************************************************************************
209 Do a case-insensitive, whitespace-ignoring string compare.
210 ***************************************************************************/
211
212 int strwicmp(const char *psz1, const char *psz2)
213 {
214         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
215         /* appropriate value. */
216         if (psz1 == psz2)
217                 return (0);
218         else if (psz1 == NULL)
219                 return (-1);
220         else if (psz2 == NULL)
221                 return (1);
222
223         /* sync the strings on first non-whitespace */
224         while (1) {
225                 while (isspace((int)*psz1))
226                         psz1++;
227                 while (isspace((int)*psz2))
228                         psz2++;
229                 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
230                     || *psz2 == '\0')
231                         break;
232                 psz1++;
233                 psz2++;
234         }
235         return (*psz1 - *psz2);
236 }
237
238
239 /*******************************************************************
240  Convert a string to upper case, but don't modify it.
241 ********************************************************************/
242
243 char *strupper_static(const char *s)
244 {
245         static pstring str;
246
247         pstrcpy(str, s);
248         strupper(str);
249
250         return str;
251 }
252
253 /*******************************************************************
254  Convert a string to "normal" form.
255 ********************************************************************/
256
257 void strnorm(char *s)
258 {
259         extern int case_default;
260         if (case_default == CASE_UPPER)
261                 strupper(s);
262         else
263                 strlower(s);
264 }
265
266 /*******************************************************************
267  Check if a string is in "normal" case.
268 ********************************************************************/
269
270 BOOL strisnormal(const char *s)
271 {
272         extern int case_default;
273         if (case_default == CASE_UPPER)
274                 return(!strhaslower(s));
275         
276         return(!strhasupper(s));
277 }
278
279
280 /****************************************************************************
281  String replace.
282  NOTE: oldc and newc must be 7 bit characters
283 ****************************************************************************/
284
285 void string_replace(char *s,char oldc,char newc)
286 {
287         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
288         string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
289         pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
290 }
291
292 /*******************************************************************
293  Skip past some strings in a buffer.
294 ********************************************************************/
295
296 char *skip_string(char *buf,size_t n)
297 {
298         while (n--)
299                 buf += strlen(buf) + 1;
300         return(buf);
301 }
302
303 /*******************************************************************
304  Count the number of characters in a string. Normally this will
305  be the same as the number of bytes in a string for single byte strings,
306  but will be different for multibyte.
307 ********************************************************************/
308
309 size_t str_charnum(const char *s)
310 {
311         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
312         return strlen_w(tmpbuf);
313 }
314
315 /*******************************************************************
316  Trim the specified elements off the front and back of a string.
317 ********************************************************************/
318
319 BOOL trim_string(char *s,const char *front,const char *back)
320 {
321         BOOL ret = False;
322         size_t front_len;
323         size_t back_len;
324         size_t len;
325
326         /* Ignore null or empty strings. */
327         if (!s || (s[0] == '\0'))
328                 return False;
329
330         front_len       = front? strlen(front) : 0;
331         back_len        = back? strlen(back) : 0;
332
333         len = strlen(s);
334
335         if (front_len) {
336                 while (len && strncmp(s, front, front_len)==0) {
337                         memcpy(s, s+front_len, (len-front_len)+1);
338                         len -= front_len;
339                         ret=True;
340                 }
341         }
342         
343         if (back_len) {
344                 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
345                         s[len-back_len]='\0';
346                         len -= back_len;
347                         ret=True;
348                 }
349         }
350         return ret;
351 }
352
353 /****************************************************************************
354  Does a string have any uppercase chars in it?
355 ****************************************************************************/
356
357 BOOL strhasupper(const char *s)
358 {
359         smb_ucs2_t *ptr;
360         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
361         for(ptr=tmpbuf;*ptr;ptr++)
362                 if(isupper_w(*ptr))
363                         return True;
364         return(False);
365 }
366
367 /****************************************************************************
368  Does a string have any lowercase chars in it?
369 ****************************************************************************/
370
371 BOOL strhaslower(const char *s)
372 {
373         smb_ucs2_t *ptr;
374         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
375         for(ptr=tmpbuf;*ptr;ptr++)
376                 if(islower_w(*ptr))
377                         return True;
378         return(False);
379 }
380
381 /****************************************************************************
382  Find the number of 'c' chars in a string
383 ****************************************************************************/
384
385 size_t count_chars(const char *s,char c)
386 {
387         smb_ucs2_t *ptr;
388         int count;
389         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
390         for(count=0,ptr=tmpbuf;*ptr;ptr++)
391                 if(*ptr==UCS2_CHAR(c))
392                         count++;
393         return(count);
394 }
395
396 /*******************************************************************
397 Return True if a string consists only of one particular character.
398 ********************************************************************/
399
400 BOOL str_is_all(const char *s,char c)
401 {
402         smb_ucs2_t *ptr;
403
404         if(s == NULL)
405                 return False;
406         if(!*s)
407                 return False;
408   
409         push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
410         for(ptr=tmpbuf;*ptr;ptr++)
411                 if(*ptr!=UCS2_CHAR(c))
412                         return False;
413
414         return True;
415 }
416
417 /*******************************************************************
418  Safe string copy into a known length string. maxlength does not
419  include the terminating zero.
420 ********************************************************************/
421
422 char *safe_strcpy(char *dest,const char *src, size_t maxlength)
423 {
424         size_t len;
425
426         if (!dest) {
427                 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
428                 return NULL;
429         }
430
431         if (!src) {
432                 *dest = 0;
433                 return dest;
434         }  
435
436         len = strlen(src);
437
438         if (len > maxlength) {
439                 DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
440                          (int)(len-maxlength), src));
441                 len = maxlength;
442         }
443       
444         memmove(dest, src, len);
445         dest[len] = 0;
446         return dest;
447 }  
448
449 /*******************************************************************
450  Safe string cat into a string. maxlength does not
451  include the terminating zero.
452 ********************************************************************/
453
454 char *safe_strcat(char *dest, const char *src, size_t maxlength)
455 {
456         size_t src_len, dest_len;
457
458         if (!dest) {
459                 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
460                 return NULL;
461         }
462
463         if (!src)
464                 return dest;
465         
466         src_len = strlen(src);
467         dest_len = strlen(dest);
468         
469         if (src_len + dest_len > maxlength) {
470                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
471                          (int)(src_len + dest_len - maxlength), src));
472                 src_len = maxlength - dest_len;
473         }
474         
475         memcpy(&dest[dest_len], src, src_len);
476         dest[dest_len + src_len] = 0;
477         return dest;
478 }
479
480 /*******************************************************************
481  Paranoid strcpy into a buffer of given length (includes terminating
482  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
483  and replaces with '_'. Deliberately does *NOT* check for multibyte
484  characters. Don't change it !
485 ********************************************************************/
486
487 char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
488 {
489         size_t len, i;
490
491         if (!dest) {
492                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
493                 return NULL;
494         }
495
496         if (!src) {
497                 *dest = 0;
498                 return dest;
499         }  
500
501         len = strlen(src);
502         if (len >= maxlength)
503                 len = maxlength - 1;
504
505         if (!other_safe_chars)
506                 other_safe_chars = "";
507
508         for(i = 0; i < len; i++) {
509                 int val = (src[i] & 0xff);
510                 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
511                         dest[i] = src[i];
512                 else
513                         dest[i] = '_';
514         }
515
516         dest[i] = '\0';
517
518         return dest;
519 }
520
521 /****************************************************************************
522  Like strncpy but always null terminates. Make sure there is room!
523  The variable n should always be one less than the available size.
524 ****************************************************************************/
525
526 char *StrnCpy(char *dest,const char *src,size_t n)
527 {
528         char *d = dest;
529         if (!dest)
530                 return(NULL);
531         if (!src) {
532                 *dest = 0;
533                 return(dest);
534         }
535         while (n-- && (*d++ = *src++))
536                 ;
537         *d = 0;
538         return(dest);
539 }
540
541 /****************************************************************************
542  Like strncpy but copies up to the character marker.  always null terminates.
543  returns a pointer to the character marker in the source string (src).
544 ****************************************************************************/
545
546 char *strncpyn(char *dest, const char *src, size_t n, char c)
547 {
548         char *p;
549         size_t str_len;
550
551         p = strchr_m(src, c);
552         if (p == NULL) {
553                 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
554                 return NULL;
555         }
556
557         str_len = PTR_DIFF(p, src);
558         strncpy(dest, src, MIN(n, str_len));
559         dest[str_len] = '\0';
560
561         return p;
562 }
563
564 /*************************************************************
565  Routine to get hex characters and turn them into a 16 byte array.
566  the array can be variable length, and any non-hex-numeric
567  characters are skipped.  "0xnn" or "0Xnn" is specially catered
568  for.
569
570  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
571
572 **************************************************************/
573
574 size_t strhex_to_str(char *p, size_t len, const char *strhex)
575 {
576         size_t i;
577         size_t num_chars = 0;
578         unsigned char   lonybble, hinybble;
579         const char     *hexchars = "0123456789ABCDEF";
580         char           *p1 = NULL, *p2 = NULL;
581
582         for (i = 0; i < len && strhex[i] != 0; i++) {
583                 if (strnequal(hexchars, "0x", 2)) {
584                         i++; /* skip two chars */
585                         continue;
586                 }
587
588                 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
589                         break;
590
591                 i++; /* next hex digit */
592
593                 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
594                         break;
595
596                 /* get the two nybbles */
597                 hinybble = PTR_DIFF(p1, hexchars);
598                 lonybble = PTR_DIFF(p2, hexchars);
599
600                 p[num_chars] = (hinybble << 4) | lonybble;
601                 num_chars++;
602
603                 p1 = NULL;
604                 p2 = NULL;
605         }
606         return num_chars;
607 }
608
609 /****************************************************************************
610  Check if a string is part of a list.
611 ****************************************************************************/
612
613 BOOL in_list(char *s,char *list,BOOL casesensitive)
614 {
615         pstring tok;
616         const char *p=list;
617
618         if (!list)
619                 return(False);
620
621         while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
622                 if (casesensitive) {
623                         if (strcmp(tok,s) == 0)
624                                 return(True);
625                 } else {
626                         if (StrCaseCmp(tok,s) == 0)
627                                 return(True);
628                 }
629         }
630         return(False);
631 }
632
633 /* this is used to prevent lots of mallocs of size 1 */
634 static char *null_string = NULL;
635
636 /****************************************************************************
637  Set a string value, allocing the space for the string
638 ****************************************************************************/
639
640 static BOOL string_init(char **dest,const char *src)
641 {
642         size_t l;
643         if (!src)     
644                 src = "";
645
646         l = strlen(src);
647
648         if (l == 0) {
649                 if (!null_string) {
650                         if((null_string = (char *)malloc(1)) == NULL) {
651                                 DEBUG(0,("string_init: malloc fail for null_string.\n"));
652                                 return False;
653                         }
654                         *null_string = 0;
655                 }
656                 *dest = null_string;
657         } else {
658                 (*dest) = (char *)malloc(l+1);
659                 if ((*dest) == NULL) {
660                         DEBUG(0,("Out of memory in string_init\n"));
661                         return False;
662                 }
663
664                 pstrcpy(*dest,src);
665         }
666         return(True);
667 }
668
669 /****************************************************************************
670  Free a string value.
671 ****************************************************************************/
672
673 void string_free(char **s)
674 {
675         if (!s || !(*s))
676                 return;
677         if (*s == null_string)
678                 *s = NULL;
679         SAFE_FREE(*s);
680 }
681
682 /****************************************************************************
683  Set a string value, deallocating any existing space, and allocing the space
684  for the string
685 ****************************************************************************/
686
687 BOOL string_set(char **dest,const char *src)
688 {
689         string_free(dest);
690         return(string_init(dest,src));
691 }
692
693 /****************************************************************************
694  Substitute a string for a pattern in another string. Make sure there is 
695  enough room!
696
697  This routine looks for pattern in s and replaces it with 
698  insert. It may do multiple replacements.
699
700  Any of " ; ' $ or ` in the insert string are replaced with _
701  if len==0 then the string cannot be extended. This is different from the old
702  use of len==0 which was for no length checks to be done.
703 ****************************************************************************/
704
705 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
706 {
707         char *p;
708         ssize_t ls,lp,li, i;
709
710         if (!insert || !pattern || !*pattern || !s)
711                 return;
712
713         ls = (ssize_t)strlen(s);
714         lp = (ssize_t)strlen(pattern);
715         li = (ssize_t)strlen(insert);
716
717         if (len == 0)
718                 len = ls + 1; /* len is number of *bytes* */
719
720         while (lp <= ls && (p = strstr(s,pattern))) {
721                 if (ls + (li-lp) >= len) {
722                         DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n", 
723                                  (int)(ls + (li-lp) - len),
724                                  pattern, (int)len));
725                         break;
726                 }
727                 if (li != lp) {
728                         memmove(p+li,p+lp,strlen(p+lp)+1);
729                 }
730                 for (i=0;i<li;i++) {
731                         switch (insert[i]) {
732                         case '`':
733                         case '"':
734                         case '\'':
735                         case ';':
736                         case '$':
737                         case '%':
738                         case '\r':
739                         case '\n':
740                                 p[i] = '_';
741                                 break;
742                         default:
743                                 p[i] = insert[i];
744                         }
745                 }
746                 s = p + li;
747                 ls += (li-lp);
748         }
749 }
750
751 void fstring_sub(char *s,const char *pattern,const char *insert)
752 {
753         string_sub(s, pattern, insert, sizeof(fstring));
754 }
755
756 void pstring_sub(char *s,const char *pattern,const char *insert)
757 {
758         string_sub(s, pattern, insert, sizeof(pstring));
759 }
760
761 /****************************************************************************
762  Similar to string_sub, but it will accept only allocated strings
763  and may realloc them so pay attention at what you pass on no
764  pointers inside strings, no pstrings or const may be passed
765  as string.
766 ****************************************************************************/
767
768 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
769 {
770         char *p, *in;
771         char *s;
772         ssize_t ls,lp,li,ld, i;
773
774         if (!insert || !pattern || !*pattern || !string || !*string)
775                 return NULL;
776
777         s = string;
778
779         in = strdup(insert);
780         if (!in) {
781                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
782                 return NULL;
783         }
784         ls = (ssize_t)strlen(s);
785         lp = (ssize_t)strlen(pattern);
786         li = (ssize_t)strlen(insert);
787         ld = li - lp;
788         for (i=0;i<li;i++) {
789                 switch (in[i]) {
790                         case '`':
791                         case '"':
792                         case '\'':
793                         case ';':
794                         case '$':
795                         case '%':
796                         case '\r':
797                         case '\n':
798                                 in[i] = '_';
799                         default:
800                                 /* ok */
801                                 break;
802                 }
803         }
804         
805         while ((p = strstr(s,pattern))) {
806                 if (ld > 0) {
807                         char *t = Realloc(string, ls + ld + 1);
808                         if (!t) {
809                                 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
810                                 SAFE_FREE(in);
811                                 return NULL;
812                         }
813                         string = t;
814                         p = t + (p - s);
815                 }
816                 if (li != lp) {
817                         memmove(p+li,p+lp,strlen(p+lp)+1);
818                 }
819                 memcpy(p, in, li);
820                 s = p + li;
821                 ls += ld;
822         }
823         SAFE_FREE(in);
824         return string;
825 }
826
827 /****************************************************************************
828  Similar to string_sub() but allows for any character to be substituted. 
829  Use with caution!
830  if len==0 then the string cannot be extended. This is different from the old
831  use of len==0 which was for no length checks to be done.
832 ****************************************************************************/
833
834 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
835 {
836         char *p;
837         ssize_t ls,lp,li;
838
839         if (!insert || !pattern || !s)
840                 return;
841
842         ls = (ssize_t)strlen(s);
843         lp = (ssize_t)strlen(pattern);
844         li = (ssize_t)strlen(insert);
845
846         if (!*pattern)
847                 return;
848         
849         if (len == 0)
850                 len = ls + 1; /* len is number of *bytes* */
851         
852         while (lp <= ls && (p = strstr(s,pattern))) {
853                 if (ls + (li-lp) >= len) {
854                         DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n", 
855                                  (int)(ls + (li-lp) - len),
856                                  pattern, (int)len));
857                         break;
858                 }
859                 if (li != lp) {
860                         memmove(p+li,p+lp,strlen(p+lp)+1);
861                 }
862                 memcpy(p, insert, li);
863                 s = p + li;
864                 ls += (li-lp);
865         }
866 }
867
868 /****************************************************************************
869  Similar to all_string_sub but for unicode strings.
870  Return a new allocated unicode string.
871  similar to string_sub() but allows for any character to be substituted.
872  Use with caution!
873 ****************************************************************************/
874
875 smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
876                                 const smb_ucs2_t *insert)
877 {
878         smb_ucs2_t *r, *rp;
879         const smb_ucs2_t *sp;
880         size_t  lr, lp, li, lt;
881
882         if (!insert || !pattern || !*pattern || !s)
883                 return NULL;
884
885         lt = (size_t)strlen_w(s);
886         lp = (size_t)strlen_w(pattern);
887         li = (size_t)strlen_w(insert);
888
889         if (li > lp) {
890                 const smb_ucs2_t *st = s;
891                 int ld = li - lp;
892                 while ((sp = strstr_w(st, pattern))) {
893                         st = sp + lp;
894                         lt += ld;
895                 }
896         }
897
898         r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
899         if (!r) {
900                 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
901                 return NULL;
902         }
903
904         while ((sp = strstr_w(s, pattern))) {
905                 memcpy(rp, s, (sp - s));
906                 rp += ((sp - s) / sizeof(smb_ucs2_t));
907                 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
908                 s = sp + lp;
909                 rp += li;
910         }
911         lr = ((rp - r) / sizeof(smb_ucs2_t));
912         if (lr < lt) {
913                 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
914                 rp += (lt - lr);
915         }
916         *rp = 0;
917
918         return r;
919 }
920
921 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
922                                              const char *insert)
923 {
924         wpstring p, i;
925
926         if (!insert || !pattern || !s)
927                 return NULL;
928         push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
929         push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
930         return all_string_sub_w(s, p, i);
931 }
932
933 /****************************************************************************
934  Splits out the front and back at a separator.
935 ****************************************************************************/
936
937 void split_at_last_component(char *path, char *front, char sep, char *back)
938 {
939         char *p = strrchr_m(path, sep);
940
941         if (p != NULL)
942                 *p = 0;
943
944         if (front != NULL)
945                 pstrcpy(front, path);
946
947         if (p != NULL) {
948                 if (back != NULL)
949                         pstrcpy(back, p+1);
950                 *p = '\\';
951         } else {
952                 if (back != NULL)
953                         back[0] = 0;
954         }
955 }
956
957 /****************************************************************************
958  Write an octal as a string.
959 ****************************************************************************/
960
961 const char *octal_string(int i)
962 {
963         static char ret[64];
964         if (i == -1)
965                 return "-1";
966         slprintf(ret, sizeof(ret)-1, "0%o", i);
967         return ret;
968 }
969
970
971 /****************************************************************************
972  Truncate a string at a specified length.
973 ****************************************************************************/
974
975 char *string_truncate(char *s, int length)
976 {
977         if (s && strlen(s) > length)
978                 s[length] = 0;
979         return s;
980 }
981
982 /****************************************************************************
983  Strchr and strrchr_m are very hard to do on general multi-byte strings. 
984  We convert via ucs2 for now.
985 ****************************************************************************/
986
987 char *strchr_m(const char *s, char c)
988 {
989         wpstring ws;
990         pstring s2;
991         smb_ucs2_t *p;
992
993         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
994         p = strchr_w(ws, UCS2_CHAR(c));
995         if (!p)
996                 return NULL;
997         *p = 0;
998         pull_ucs2_pstring(s2, ws);
999         return (char *)(s+strlen(s2));
1000 }
1001
1002 char *strrchr_m(const char *s, char c)
1003 {
1004         wpstring ws;
1005         pstring s2;
1006         smb_ucs2_t *p;
1007
1008         push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1009         p = strrchr_w(ws, UCS2_CHAR(c));
1010         if (!p)
1011                 return NULL;
1012         *p = 0;
1013         pull_ucs2_pstring(s2, ws);
1014         return (char *)(s+strlen(s2));
1015 }
1016
1017 /*******************************************************************
1018  Convert a string to lower case.
1019 ********************************************************************/
1020
1021 void strlower_m(char *s)
1022 {
1023         /* this is quite a common operation, so we want it to be
1024            fast. We optimise for the ascii case, knowing that all our
1025            supported multi-byte character sets are ascii-compatible
1026            (ie. they match for the first 128 chars) */
1027
1028         while (*s && !(((unsigned char)s[0]) & 0x7F))
1029                 *s++ = tolower((unsigned char)*s);
1030
1031         if (!*s)
1032                 return;
1033
1034         /* I assume that lowercased string takes the same number of bytes
1035          * as source string even in UTF-8 encoding. (VIV) */
1036         unix_strlower(s,strlen(s)+1,s,strlen(s)+1);     
1037 }
1038
1039 /*******************************************************************
1040  Duplicate convert a string to lower case.
1041 ********************************************************************/
1042
1043 char *strdup_lower(const char *s)
1044 {
1045         char *t = strdup(s);
1046         if (t == NULL) {
1047                 DEBUG(0, ("strdup_lower: Out of memory!\n"));
1048                 return NULL;
1049         }
1050         strlower_m(t);
1051         return t;
1052 }
1053
1054 /*******************************************************************
1055  Convert a string to upper case.
1056 ********************************************************************/
1057
1058 void strupper_m(char *s)
1059 {
1060         /* this is quite a common operation, so we want it to be
1061            fast. We optimise for the ascii case, knowing that all our
1062            supported multi-byte character sets are ascii-compatible
1063            (ie. they match for the first 128 chars) */
1064
1065         while (*s && !(((unsigned char)s[0]) & 0x7F))
1066                 *s++ = toupper((unsigned char)*s);
1067
1068         if (!*s)
1069                 return;
1070
1071         /* I assume that lowercased string takes the same number of bytes
1072          * as source string even in multibyte encoding. (VIV) */
1073         unix_strupper(s,strlen(s)+1,s,strlen(s)+1);     
1074 }
1075
1076 /*******************************************************************
1077  Convert a string to upper case.
1078 ********************************************************************/
1079
1080 char *strdup_upper(const char *s)
1081 {
1082         char *t = strdup(s);
1083         if (t == NULL) {
1084                 DEBUG(0, ("strdup_upper: Out of memory!\n"));
1085                 return NULL;
1086         }
1087         strupper_m(t);
1088         return t;
1089 }
1090
1091 /*******************************************************************
1092  Return a RFC2254 binary string representation of a buffer.
1093  Used in LDAP filters.
1094  Caller must free.
1095 ********************************************************************/
1096
1097 char *binary_string(char *buf, int len)
1098 {
1099         char *s;
1100         int i, j;
1101         const char *hex = "0123456789ABCDEF";
1102         s = malloc(len * 3 + 1);
1103         if (!s)
1104                 return NULL;
1105         for (j=i=0;i<len;i++) {
1106                 s[j] = '\\';
1107                 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1108                 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1109                 j += 3;
1110         }
1111         s[j] = 0;
1112         return s;
1113 }
1114
1115 /*******************************************************************
1116  Just a typesafety wrapper for snprintf into a pstring.
1117 ********************************************************************/
1118
1119 int pstr_sprintf(pstring s, const char *fmt, ...)
1120 {
1121         va_list ap;
1122         int ret;
1123
1124         va_start(ap, fmt);
1125         ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1126         va_end(ap);
1127         return ret;
1128 }
1129
1130 /*******************************************************************
1131  Just a typesafety wrapper for snprintf into a fstring.
1132 ********************************************************************/
1133
1134 int fstr_sprintf(fstring s, const char *fmt, ...)
1135 {
1136         va_list ap;
1137         int ret;
1138
1139         va_start(ap, fmt);
1140         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1141         va_end(ap);
1142         return ret;
1143 }
1144
1145 #ifndef HAVE_STRNDUP
1146 /*******************************************************************
1147  Some platforms don't have strndup.
1148 ********************************************************************/
1149
1150  char *strndup(const char *s, size_t n)
1151 {
1152         char *ret;
1153         
1154         n = strnlen(s, n);
1155         ret = malloc(n+1);
1156         if (!ret)
1157                 return NULL;
1158         memcpy(ret, s, n);
1159         ret[n] = 0;
1160
1161         return ret;
1162 }
1163 #endif
1164
1165 #ifndef HAVE_STRNLEN
1166 /*******************************************************************
1167  Some platforms don't have strnlen
1168 ********************************************************************/
1169
1170  size_t strnlen(const char *s, size_t n)
1171 {
1172         int i;
1173         for (i=0; s[i] && i<n; i++)
1174                 /* noop */ ;
1175         return i;
1176 }
1177 #endif
1178
1179 /***********************************************************
1180  List of Strings manipulation functions
1181 ***********************************************************/
1182
1183 #define S_LIST_ABS 16 /* List Allocation Block Size */
1184
1185 char **str_list_make(const char *string, const char *sep)
1186 {
1187         char **list, **rlist;
1188         const char *str;
1189         char *s;
1190         int num, lsize;
1191         pstring tok;
1192         
1193         if (!string || !*string)
1194                 return NULL;
1195         s = strdup(string);
1196         if (!s) {
1197                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1198                 return NULL;
1199         }
1200         if (!sep) sep = LIST_SEP;
1201         
1202         num = lsize = 0;
1203         list = NULL;
1204         
1205         str = s;
1206         while (next_token(&str, tok, sep, sizeof(tok))) {               
1207                 if (num == lsize) {
1208                         lsize += S_LIST_ABS;
1209                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1210                         if (!rlist) {
1211                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1212                                 str_list_free(&list);
1213                                 SAFE_FREE(s);
1214                                 return NULL;
1215                         } else
1216                                 list = rlist;
1217                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1218                 }
1219                 
1220                 list[num] = strdup(tok);
1221                 if (!list[num]) {
1222                         DEBUG(0,("str_list_make: Unable to allocate memory"));
1223                         str_list_free(&list);
1224                         SAFE_FREE(s);
1225                         return NULL;
1226                 }
1227         
1228                 num++;  
1229         }
1230         
1231         SAFE_FREE(s);
1232         return list;
1233 }
1234
1235 BOOL str_list_copy(char ***dest, const char **src)
1236 {
1237         char **list, **rlist;
1238         int num, lsize;
1239         
1240         *dest = NULL;
1241         if (!src)
1242                 return False;
1243         
1244         num = lsize = 0;
1245         list = NULL;
1246                 
1247         while (src[num]) {
1248                 if (num == lsize) {
1249                         lsize += S_LIST_ABS;
1250                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1251                         if (!rlist) {
1252                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1253                                 str_list_free(&list);
1254                                 return False;
1255                         } else
1256                                 list = rlist;
1257                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1258                 }
1259                 
1260                 list[num] = strdup(src[num]);
1261                 if (!list[num]) {
1262                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
1263                         str_list_free(&list);
1264                         return False;
1265                 }
1266
1267                 num++;
1268         }
1269         
1270         *dest = list;
1271         return True;    
1272 }
1273
1274 /***********************************************************
1275  Return true if all the elements of the list match exactly.
1276 ***********************************************************/
1277
1278 BOOL str_list_compare(char **list1, char **list2)
1279 {
1280         int num;
1281         
1282         if (!list1 || !list2)
1283                 return (list1 == list2); 
1284         
1285         for (num = 0; list1[num]; num++) {
1286                 if (!list2[num])
1287                         return False;
1288                 if (!strcsequal(list1[num], list2[num]))
1289                         return False;
1290         }
1291         if (list2[num])
1292                 return False; /* if list2 has more elements than list1 fail */
1293         
1294         return True;
1295 }
1296
1297 void str_list_free(char ***list)
1298 {
1299         char **tlist;
1300         
1301         if (!list || !*list)
1302                 return;
1303         tlist = *list;
1304         for(; *tlist; tlist++)
1305                 SAFE_FREE(*tlist);
1306         SAFE_FREE(*list);
1307 }
1308
1309 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1310 {
1311         char *p, *s, *t;
1312         ssize_t ls, lp, li, ld, i, d;
1313
1314         if (!list)
1315                 return False;
1316         if (!pattern)
1317                 return False;
1318         if (!insert)
1319                 return False;
1320
1321         lp = (ssize_t)strlen(pattern);
1322         li = (ssize_t)strlen(insert);
1323         ld = li -lp;
1324                         
1325         while (*list) {
1326                 s = *list;
1327                 ls = (ssize_t)strlen(s);
1328
1329                 while ((p = strstr(s, pattern))) {
1330                         t = *list;
1331                         d = p -t;
1332                         if (ld) {
1333                                 t = (char *) malloc(ls +ld +1);
1334                                 if (!t) {
1335                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1336                                         return False;
1337                                 }
1338                                 memcpy(t, *list, d);
1339                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1340                                 SAFE_FREE(*list);
1341                                 *list = t;
1342                                 ls += ld;
1343                                 s = t +d +li;
1344                         }
1345                         
1346                         for (i = 0; i < li; i++) {
1347                                 switch (insert[i]) {
1348                                         case '`':
1349                                         case '"':
1350                                         case '\'':
1351                                         case ';':
1352                                         case '$':
1353                                         case '%':
1354                                         case '\r':
1355                                         case '\n':
1356                                                 t[d +i] = '_';
1357                                                 break;
1358                                         default:
1359                                                 t[d +i] = insert[i];
1360                                 }
1361                         }       
1362                 }
1363                 
1364                 list++;
1365         }
1366         
1367         return True;
1368 }
1369
1370
1371 #define IPSTR_LIST_SEP  ","
1372
1373 /**
1374  * Add ip string representation to ipstr list. Used also
1375  * as part of @function ipstr_list_make
1376  *
1377  * @param ipstr_list pointer to string containing ip list;
1378  *        MUST BE already allocated and IS reallocated if necessary
1379  * @param ipstr_size pointer to current size of ipstr_list (might be changed
1380  *        as a result of reallocation)
1381  * @param ip IP address which is to be added to list
1382  * @return pointer to string appended with new ip and possibly
1383  *         reallocated to new length
1384  **/
1385
1386 char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip)
1387 {
1388         char* new_ipstr = NULL;
1389         
1390         /* arguments checking */
1391         if (!ipstr_list || !ip) return NULL;
1392
1393         /* attempt to convert ip to a string and append colon separator to it */
1394         if (*ipstr_list) {
1395                 asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip));
1396                 SAFE_FREE(*ipstr_list);
1397         } else {
1398                 asprintf(&new_ipstr, "%s", inet_ntoa(*ip));
1399         }
1400         *ipstr_list = new_ipstr;
1401         return *ipstr_list;
1402 }
1403
1404
1405 /**
1406  * Allocate and initialise an ipstr list using ip adresses
1407  * passed as arguments.
1408  *
1409  * @param ipstr_list pointer to string meant to be allocated and set
1410  * @param ip_list array of ip addresses to place in the list
1411  * @param ip_count number of addresses stored in ip_list
1412  * @return pointer to allocated ip string
1413  **/
1414  
1415 char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count)
1416 {
1417         int i;
1418         
1419         /* arguments checking */
1420         if (!ip_list && !ipstr_list) return 0;
1421
1422         *ipstr_list = NULL;
1423         
1424         /* process ip addresses given as arguments */
1425         for (i = 0; i < ip_count; i++)
1426                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1427         
1428         return (*ipstr_list);
1429 }
1430
1431
1432 /**
1433  * Parse given ip string list into array of ip addresses
1434  * (as in_addr structures)
1435  *
1436  * @param ipstr ip string list to be parsed 
1437  * @param ip_list pointer to array of ip addresses which is
1438  *        allocated by this function and must be freed by caller
1439  * @return number of succesfully parsed addresses
1440  **/
1441  
1442 int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list)
1443 {
1444         fstring token_str;
1445         int count;
1446
1447         if (!ipstr_list || !ip_list) return 0;
1448         
1449         for (*ip_list = NULL, count = 0;
1450              next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN);
1451              count++) {
1452              
1453                 struct in_addr addr;
1454
1455                 /* convert single token to ip address */
1456                 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1457                         break;
1458                 
1459                 /* prepare place for another in_addr structure */
1460                 *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr));
1461                 if (!*ip_list) return -1;
1462                 
1463                 (*ip_list)[count] = addr;
1464         }
1465         
1466         return count;
1467 }
1468
1469
1470 /**
1471  * Safely free ip string list
1472  *
1473  * @param ipstr_list ip string list to be freed
1474  **/
1475
1476 void ipstr_list_free(char* ipstr_list)
1477 {
1478         SAFE_FREE(ipstr_list);
1479 }
1480
1481
1482 /***********************************************************
1483  Unescape a URL encoded string, in place.
1484 ***********************************************************/
1485
1486 void rfc1738_unescape(char *buf)
1487 {
1488         char *p=buf;
1489
1490         while ((p=strchr_m(p,'+')))
1491                 *p = ' ';
1492
1493         p = buf;
1494
1495         while (p && *p && (p=strchr_m(p,'%'))) {
1496                 int c1 = p[1];
1497                 int c2 = p[2];
1498
1499                 if (c1 >= '0' && c1 <= '9')
1500                         c1 = c1 - '0';
1501                 else if (c1 >= 'A' && c1 <= 'F')
1502                         c1 = 10 + c1 - 'A';
1503                 else if (c1 >= 'a' && c1 <= 'f')
1504                         c1 = 10 + c1 - 'a';
1505                 else {p++; continue;}
1506
1507                 if (c2 >= '0' && c2 <= '9')
1508                         c2 = c2 - '0';
1509                 else if (c2 >= 'A' && c2 <= 'F')
1510                         c2 = 10 + c2 - 'A';
1511                 else if (c2 >= 'a' && c2 <= 'f')
1512                         c2 = 10 + c2 - 'a';
1513                 else {p++; continue;}
1514                         
1515                 *p = (c1<<4) | c2;
1516
1517                 memmove(p+1, p+3, strlen(p+3)+1);
1518                 p++;
1519         }
1520 }
1521
1522 #ifdef VALGRIND
1523 size_t valgrind_strlen(const char *s)
1524 {
1525         size_t count;
1526         for(count = 0; *s++; count++)
1527                 ;
1528         return count;
1529 }
1530 #endif