6d1f8fe023b137991b6c4f15d7f6940aef20f864
[samba.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(char **ptr,char *buff, const char *sep, size_t bufsize)
32 {
33         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(char **ptr,char *buff, const char *sep, size_t bufsize)
79 {
80         BOOL ret;
81         if (!ptr)
82                 ptr = &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         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         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 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         char *str, *s;
1189         int num, lsize;
1190         pstring tok;
1191         
1192         if (!string || !*string)
1193                 return NULL;
1194         s = strdup(string);
1195         if (!s) {
1196                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1197                 return NULL;
1198         }
1199         if (!sep) sep = LIST_SEP;
1200         
1201         num = lsize = 0;
1202         list = NULL;
1203         
1204         str = s;
1205         while (next_token(&str, tok, sep, sizeof(tok))) {               
1206                 if (num == lsize) {
1207                         lsize += S_LIST_ABS;
1208                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1209                         if (!rlist) {
1210                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
1211                                 str_list_free(&list);
1212                                 SAFE_FREE(s);
1213                                 return NULL;
1214                         } else
1215                                 list = rlist;
1216                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1217                 }
1218                 
1219                 list[num] = strdup(tok);
1220                 if (!list[num]) {
1221                         DEBUG(0,("str_list_make: Unable to allocate memory"));
1222                         str_list_free(&list);
1223                         SAFE_FREE(s);
1224                         return NULL;
1225                 }
1226         
1227                 num++;  
1228         }
1229         
1230         SAFE_FREE(s);
1231         return list;
1232 }
1233
1234 BOOL str_list_copy(char ***dest, char **src)
1235 {
1236         char **list, **rlist;
1237         int num, lsize;
1238         
1239         *dest = NULL;
1240         if (!src)
1241                 return False;
1242         
1243         num = lsize = 0;
1244         list = NULL;
1245                 
1246         while (src[num]) {
1247                 if (num == lsize) {
1248                         lsize += S_LIST_ABS;
1249                         rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1250                         if (!rlist) {
1251                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1252                                 str_list_free(&list);
1253                                 return False;
1254                         } else
1255                                 list = rlist;
1256                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1257                 }
1258                 
1259                 list[num] = strdup(src[num]);
1260                 if (!list[num]) {
1261                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
1262                         str_list_free(&list);
1263                         return False;
1264                 }
1265
1266                 num++;
1267         }
1268         
1269         *dest = list;
1270         return True;    
1271 }
1272
1273 /***********************************************************
1274  Return true if all the elements of the list match exactly.
1275 ***********************************************************/
1276
1277 BOOL str_list_compare(char **list1, char **list2)
1278 {
1279         int num;
1280         
1281         if (!list1 || !list2)
1282                 return (list1 == list2); 
1283         
1284         for (num = 0; list1[num]; num++) {
1285                 if (!list2[num])
1286                         return False;
1287                 if (!strcsequal(list1[num], list2[num]))
1288                         return False;
1289         }
1290         if (list2[num])
1291                 return False; /* if list2 has more elements than list1 fail */
1292         
1293         return True;
1294 }
1295
1296 void str_list_free(char ***list)
1297 {
1298         char **tlist;
1299         
1300         if (!list || !*list)
1301                 return;
1302         tlist = *list;
1303         for(; *tlist; tlist++)
1304                 SAFE_FREE(*tlist);
1305         SAFE_FREE(*list);
1306 }
1307
1308 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1309 {
1310         char *p, *s, *t;
1311         ssize_t ls, lp, li, ld, i, d;
1312
1313         if (!list)
1314                 return False;
1315         if (!pattern)
1316                 return False;
1317         if (!insert)
1318                 return False;
1319
1320         lp = (ssize_t)strlen(pattern);
1321         li = (ssize_t)strlen(insert);
1322         ld = li -lp;
1323                         
1324         while (*list) {
1325                 s = *list;
1326                 ls = (ssize_t)strlen(s);
1327
1328                 while ((p = strstr(s, pattern))) {
1329                         t = *list;
1330                         d = p -t;
1331                         if (ld) {
1332                                 t = (char *) malloc(ls +ld +1);
1333                                 if (!t) {
1334                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1335                                         return False;
1336                                 }
1337                                 memcpy(t, *list, d);
1338                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
1339                                 SAFE_FREE(*list);
1340                                 *list = t;
1341                                 ls += ld;
1342                                 s = t +d +li;
1343                         }
1344                         
1345                         for (i = 0; i < li; i++) {
1346                                 switch (insert[i]) {
1347                                         case '`':
1348                                         case '"':
1349                                         case '\'':
1350                                         case ';':
1351                                         case '$':
1352                                         case '%':
1353                                         case '\r':
1354                                         case '\n':
1355                                                 t[d +i] = '_';
1356                                                 break;
1357                                         default:
1358                                                 t[d +i] = insert[i];
1359                                 }
1360                         }       
1361                 }
1362                 
1363                 list++;
1364         }
1365         
1366         return True;
1367 }