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