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