source: trunk-3.0/source/lib/util_str.c@ 102

Last change on this file since 102 was 60, checked in by Yuri Dario, 18 years ago

Use popen() for executing scripts, so .cmd/.exe/.sh scripts are supported. Fixes ticket:12 (and probably also ticket:26).

File size: 59.6 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Samba utility functions
4
5 Copyright (C) Andrew Tridgell 1992-2001
6 Copyright (C) Simo Sorce 2001-2002
7 Copyright (C) Martin Pool 2003
8 Copyright (C) James Peach 2006
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23*/
24
25#include "includes.h"
26
27/**
28 * @file
29 * @brief String utilities.
30 **/
31
32/**
33 * Internal function to get the next token from a string, return False if none
34 * found. Handles double-quotes. This is the work horse function called by
35 * next_token() and next_token_no_ltrim().
36 *
37 * Based on a routine by GJC@VILLAGE.COM.
38 * Extensively modified by Andrew.Tridgell@anu.edu.au
39 */
40static BOOL next_token_internal(const char **ptr,
41 char *buff,
42 const char *sep,
43 size_t bufsize,
44 BOOL ltrim)
45{
46 char *s;
47 char *pbuf;
48 BOOL quoted;
49 size_t len=1;
50
51 if (!ptr)
52 return(False);
53
54 s = (char *)*ptr;
55
56 /* default to simple separators */
57 if (!sep)
58 sep = " \t\n\r";
59
60 /* find the first non sep char, if left-trimming is requested */
61 if (ltrim) {
62 while (*s && strchr_m(sep,*s))
63 s++;
64 }
65
66 /* nothing left? */
67 if (! *s)
68 return(False);
69
70 /* copy over the token */
71 pbuf = buff;
72 for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
73 if ( *s == '\"' ) {
74 quoted = !quoted;
75 } else {
76 len++;
77 *pbuf++ = *s;
78 }
79 }
80
81 *ptr = (*s) ? s+1 : s;
82 *pbuf = 0;
83
84 return(True);
85}
86
87/*
88 * Get the next token from a string, return False if none found. Handles
89 * double-quotes. This version trims leading separator characters before
90 * looking for a token.
91 */
92BOOL next_token(const char **ptr, char *buff, const char *sep, size_t bufsize)
93{
94 return next_token_internal(ptr, buff, sep, bufsize, True);
95}
96
97/*
98 * Get the next token from a string, return False if none found. Handles
99 * double-quotes. This version does not trim leading separator characters
100 * before looking for a token.
101 */
102BOOL next_token_no_ltrim(const char **ptr,
103 char *buff,
104 const char *sep,
105 size_t bufsize)
106{
107 return next_token_internal(ptr, buff, sep, bufsize, False);
108}
109
110/**
111This is like next_token but is not re-entrant and "remembers" the first
112parameter so you can pass NULL. This is useful for user interface code
113but beware the fact that it is not re-entrant!
114**/
115
116static const char *last_ptr=NULL;
117
118BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
119{
120 BOOL ret;
121 if (!ptr)
122 ptr = &last_ptr;
123
124 ret = next_token(ptr, buff, sep, bufsize);
125 last_ptr = *ptr;
126 return ret;
127}
128
129static uint16 tmpbuf[sizeof(pstring)];
130
131void set_first_token(char *ptr)
132{
133 last_ptr = ptr;
134}
135
136/**
137 Convert list of tokens to array; dependent on above routine.
138 Uses last_ptr from above - bit of a hack.
139**/
140
141char **toktocliplist(int *ctok, const char *sep)
142{
143 char *s=(char *)last_ptr;
144 int ictok=0;
145 char **ret, **iret;
146
147 if (!sep)
148 sep = " \t\n\r";
149
150 while(*s && strchr_m(sep,*s))
151 s++;
152
153 /* nothing left? */
154 if (!*s)
155 return(NULL);
156
157 do {
158 ictok++;
159 while(*s && (!strchr_m(sep,*s)))
160 s++;
161 while(*s && strchr_m(sep,*s))
162 *s++=0;
163 } while(*s);
164
165 *ctok=ictok;
166 s=(char *)last_ptr;
167
168 if (!(ret=iret=SMB_MALLOC_ARRAY(char *,ictok+1)))
169 return NULL;
170
171 while(ictok--) {
172 *iret++=s;
173 if (ictok > 0) {
174 while(*s++)
175 ;
176 while(!*s)
177 s++;
178 }
179 }
180
181 ret[*ctok] = NULL;
182 return ret;
183}
184
185/**
186 * Case insensitive string compararison.
187 *
188 * iconv does not directly give us a way to compare strings in
189 * arbitrary unix character sets -- all we can is convert and then
190 * compare. This is expensive.
191 *
192 * As an optimization, we do a first pass that considers only the
193 * prefix of the strings that is entirely 7-bit. Within this, we
194 * check whether they have the same value.
195 *
196 * Hopefully this will often give the answer without needing to copy.
197 * In particular it should speed comparisons to literal ascii strings
198 * or comparisons of strings that are "obviously" different.
199 *
200 * If we find a non-ascii character we fall back to converting via
201 * iconv.
202 *
203 * This should never be slower than convering the whole thing, and
204 * often faster.
205 *
206 * A different optimization would be to compare for bitwise equality
207 * in the binary encoding. (It would be possible thought hairy to do
208 * both simultaneously.) But in that case if they turn out to be
209 * different, we'd need to restart the whole thing.
210 *
211 * Even better is to implement strcasecmp for each encoding and use a
212 * function pointer.
213 **/
214int StrCaseCmp(const char *s, const char *t)
215{
216
217 const char *ps, *pt;
218 size_t size;
219 smb_ucs2_t *buffer_s, *buffer_t;
220 int ret;
221
222 for (ps = s, pt = t; ; ps++, pt++) {
223 char us, ut;
224
225 if (!*ps && !*pt)
226 return 0; /* both ended */
227 else if (!*ps)
228 return -1; /* s is a prefix */
229 else if (!*pt)
230 return +1; /* t is a prefix */
231 else if ((*ps & 0x80) || (*pt & 0x80))
232 /* not ascii anymore, do it the hard way from here on in */
233 break;
234
235 us = toupper_ascii(*ps);
236 ut = toupper_ascii(*pt);
237 if (us == ut)
238 continue;
239 else if (us < ut)
240 return -1;
241 else if (us > ut)
242 return +1;
243 }
244
245 size = push_ucs2_allocate(&buffer_s, ps);
246 if (size == (size_t)-1) {
247 return strcmp(ps, pt);
248 /* Not quite the right answer, but finding the right one
249 under this failure case is expensive, and it's pretty close */
250 }
251
252 size = push_ucs2_allocate(&buffer_t, pt);
253 if (size == (size_t)-1) {
254 SAFE_FREE(buffer_s);
255 return strcmp(ps, pt);
256 /* Not quite the right answer, but finding the right one
257 under this failure case is expensive, and it's pretty close */
258 }
259
260 ret = strcasecmp_w(buffer_s, buffer_t);
261 SAFE_FREE(buffer_s);
262 SAFE_FREE(buffer_t);
263 return ret;
264}
265
266
267/**
268 Case insensitive string compararison, length limited.
269**/
270int StrnCaseCmp(const char *s, const char *t, size_t n)
271{
272 pstring buf1, buf2;
273 unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
274 unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
275 return strncmp(buf1,buf2,n);
276}
277
278/**
279 * Compare 2 strings.
280 *
281 * @note The comparison is case-insensitive.
282 **/
283BOOL strequal(const char *s1, const char *s2)
284{
285 if (s1 == s2)
286 return(True);
287 if (!s1 || !s2)
288 return(False);
289
290 return(StrCaseCmp(s1,s2)==0);
291}
292
293/**
294 * Compare 2 strings up to and including the nth char.
295 *
296 * @note The comparison is case-insensitive.
297 **/
298BOOL strnequal(const char *s1,const char *s2,size_t n)
299{
300 if (s1 == s2)
301 return(True);
302 if (!s1 || !s2 || !n)
303 return(False);
304
305 return(StrnCaseCmp(s1,s2,n)==0);
306}
307
308/**
309 Compare 2 strings (case sensitive).
310**/
311
312BOOL strcsequal(const char *s1,const char *s2)
313{
314 if (s1 == s2)
315 return(True);
316 if (!s1 || !s2)
317 return(False);
318
319 return(strcmp(s1,s2)==0);
320}
321
322/**
323Do a case-insensitive, whitespace-ignoring string compare.
324**/
325
326int strwicmp(const char *psz1, const char *psz2)
327{
328 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
329 /* appropriate value. */
330 if (psz1 == psz2)
331 return (0);
332 else if (psz1 == NULL)
333 return (-1);
334 else if (psz2 == NULL)
335 return (1);
336
337 /* sync the strings on first non-whitespace */
338 while (1) {
339 while (isspace((int)*psz1))
340 psz1++;
341 while (isspace((int)*psz2))
342 psz2++;
343 if (toupper_ascii(*psz1) != toupper_ascii(*psz2) || *psz1 == '\0'
344 || *psz2 == '\0')
345 break;
346 psz1++;
347 psz2++;
348 }
349 return (*psz1 - *psz2);
350}
351
352
353/**
354 Convert a string to upper case, but don't modify it.
355**/
356
357char *strupper_static(const char *s)
358{
359 static pstring str;
360
361 pstrcpy(str, s);
362 strupper_m(str);
363
364 return str;
365}
366
367/**
368 Convert a string to "normal" form.
369**/
370
371void strnorm(char *s, int case_default)
372{
373 if (case_default == CASE_UPPER)
374 strupper_m(s);
375 else
376 strlower_m(s);
377}
378
379/**
380 Check if a string is in "normal" case.
381**/
382
383BOOL strisnormal(const char *s, int case_default)
384{
385 if (case_default == CASE_UPPER)
386 return(!strhaslower(s));
387
388 return(!strhasupper(s));
389}
390
391
392/**
393 String replace.
394 NOTE: oldc and newc must be 7 bit characters
395**/
396
397void string_replace( pstring s, char oldc, char newc )
398{
399 char *p;
400
401 /* this is quite a common operation, so we want it to be
402 fast. We optimise for the ascii case, knowing that all our
403 supported multi-byte character sets are ascii-compatible
404 (ie. they match for the first 128 chars) */
405
406 for (p = s; *p; p++) {
407 if (*p & 0x80) /* mb string - slow path. */
408 break;
409 if (*p == oldc)
410 *p = newc;
411 }
412
413 if (!*p)
414 return;
415
416 /* Slow (mb) path. */
417#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
418 /* With compose characters we must restart from the beginning. JRA. */
419 p = s;
420#endif
421 push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE);
422 string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
423 pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
424}
425
426/**
427 * Skip past some strings in a buffer - old version - no checks.
428 * **/
429
430char *push_skip_string(char *buf)
431{
432 buf += strlen(buf) + 1;
433 return(buf);
434}
435
436/**
437 Skip past a string in a buffer. Buffer may not be
438 null terminated. end_ptr points to the first byte after
439 then end of the buffer.
440**/
441
442char *skip_string(const char *base, size_t len, char *buf)
443{
444 const char *end_ptr = base + len;
445
446 if (end_ptr < base || !base || !buf || buf >= end_ptr) {
447 return NULL;
448 }
449
450 /* Skip the string */
451 while (*buf) {
452 buf++;
453 if (buf >= end_ptr) {
454 return NULL;
455 }
456 }
457 /* Skip the '\0' */
458 buf++;
459 return buf;
460}
461
462/**
463 Count the number of characters in a string. Normally this will
464 be the same as the number of bytes in a string for single byte strings,
465 but will be different for multibyte.
466**/
467
468size_t str_charnum(const char *s)
469{
470 uint16 tmpbuf2[sizeof(pstring)];
471 push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
472 return strlen_w(tmpbuf2);
473}
474
475/**
476 Count the number of characters in a string. Normally this will
477 be the same as the number of bytes in a string for single byte strings,
478 but will be different for multibyte.
479**/
480
481size_t str_ascii_charnum(const char *s)
482{
483 pstring tmpbuf2;
484 push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
485 return strlen(tmpbuf2);
486}
487
488BOOL trim_char(char *s,char cfront,char cback)
489{
490 BOOL ret = False;
491 char *ep;
492 char *fp = s;
493
494 /* Ignore null or empty strings. */
495 if (!s || (s[0] == '\0'))
496 return False;
497
498 if (cfront) {
499 while (*fp && *fp == cfront)
500 fp++;
501 if (!*fp) {
502 /* We ate the string. */
503 s[0] = '\0';
504 return True;
505 }
506 if (fp != s)
507 ret = True;
508 }
509
510 ep = fp + strlen(fp) - 1;
511 if (cback) {
512 /* Attempt ascii only. Bail for mb strings. */
513 while ((ep >= fp) && (*ep == cback)) {
514 ret = True;
515 if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
516 /* Could be mb... bail back to tim_string. */
517 char fs[2], bs[2];
518 if (cfront) {
519 fs[0] = cfront;
520 fs[1] = '\0';
521 }
522 bs[0] = cback;
523 bs[1] = '\0';
524 return trim_string(s, cfront ? fs : NULL, bs);
525 } else {
526 ep--;
527 }
528 }
529 if (ep < fp) {
530 /* We ate the string. */
531 s[0] = '\0';
532 return True;
533 }
534 }
535
536 ep[1] = '\0';
537 memmove(s, fp, ep-fp+2);
538 return ret;
539}
540
541/**
542 Trim the specified elements off the front and back of a string.
543**/
544
545BOOL trim_string(char *s,const char *front,const char *back)
546{
547 BOOL ret = False;
548 size_t front_len;
549 size_t back_len;
550 size_t len;
551
552 /* Ignore null or empty strings. */
553 if (!s || (s[0] == '\0'))
554 return False;
555
556 front_len = front? strlen(front) : 0;
557 back_len = back? strlen(back) : 0;
558
559 len = strlen(s);
560
561 if (front_len) {
562 while (len && strncmp(s, front, front_len)==0) {
563 /* Must use memmove here as src & dest can
564 * easily overlap. Found by valgrind. JRA. */
565 memmove(s, s+front_len, (len-front_len)+1);
566 len -= front_len;
567 ret=True;
568 }
569 }
570
571 if (back_len) {
572 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
573 s[len-back_len]='\0';
574 len -= back_len;
575 ret=True;
576 }
577 }
578 return ret;
579}
580
581/**
582 Does a string have any uppercase chars in it?
583**/
584
585BOOL strhasupper(const char *s)
586{
587 smb_ucs2_t *ptr;
588 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
589 for(ptr=tmpbuf;*ptr;ptr++)
590 if(isupper_w(*ptr))
591 return True;
592 return(False);
593}
594
595/**
596 Does a string have any lowercase chars in it?
597**/
598
599BOOL strhaslower(const char *s)
600{
601 smb_ucs2_t *ptr;
602 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
603 for(ptr=tmpbuf;*ptr;ptr++)
604 if(islower_w(*ptr))
605 return True;
606 return(False);
607}
608
609/**
610 Find the number of 'c' chars in a string
611**/
612
613size_t count_chars(const char *s,char c)
614{
615 smb_ucs2_t *ptr;
616 int count;
617 smb_ucs2_t *alloc_tmpbuf = NULL;
618
619 if (push_ucs2_allocate(&alloc_tmpbuf, s) == (size_t)-1) {
620 return 0;
621 }
622
623 for(count=0,ptr=alloc_tmpbuf;*ptr;ptr++)
624 if(*ptr==UCS2_CHAR(c))
625 count++;
626
627 SAFE_FREE(alloc_tmpbuf);
628 return(count);
629}
630
631/**
632 Safe string copy into a known length string. maxlength does not
633 include the terminating zero.
634**/
635
636char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_t maxlength)
637{
638 size_t len;
639
640 if (!dest) {
641 DEBUG(0,("ERROR: NULL dest in safe_strcpy, called from [%s][%d]\n", fn, line));
642 return NULL;
643 }
644
645#ifdef DEVELOPER
646 clobber_region(fn,line,dest, maxlength+1);
647#endif
648
649 if (!src) {
650 *dest = 0;
651 return dest;
652 }
653
654 len = strnlen(src, maxlength+1);
655
656 if (len > maxlength) {
657 DEBUG(0,("ERROR: string overflow by %lu (%lu - %lu) in safe_strcpy [%.50s]\n",
658 (unsigned long)(len-maxlength), (unsigned long)len,
659 (unsigned long)maxlength, src));
660 len = maxlength;
661 }
662
663 memmove(dest, src, len);
664 dest[len] = 0;
665 return dest;
666}
667
668/**
669 Safe string cat into a string. maxlength does not
670 include the terminating zero.
671**/
672char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
673{
674 size_t src_len, dest_len;
675
676 if (!dest) {
677 DEBUG(0,("ERROR: NULL dest in safe_strcat, called from [%s][%d]\n", fn, line));
678 return NULL;
679 }
680
681 if (!src)
682 return dest;
683
684 src_len = strnlen(src, maxlength + 1);
685 dest_len = strnlen(dest, maxlength + 1);
686
687#ifdef DEVELOPER
688 clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
689#endif
690
691 if (src_len + dest_len > maxlength) {
692 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
693 (int)(src_len + dest_len - maxlength), src));
694 if (maxlength > dest_len) {
695 memcpy(&dest[dest_len], src, maxlength - dest_len);
696 }
697 dest[maxlength] = 0;
698 return NULL;
699 }
700
701 memcpy(&dest[dest_len], src, src_len);
702 dest[dest_len + src_len] = 0;
703 return dest;
704}
705
706/**
707 Paranoid strcpy into a buffer of given length (includes terminating
708 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
709 and replaces with '_'. Deliberately does *NOT* check for multibyte
710 characters. Don't change it !
711**/
712char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
713{
714 size_t len, i;
715
716#ifdef DEVELOPER
717 clobber_region(fn, line, dest, maxlength);
718#endif
719
720 if (!dest) {
721 DEBUG(0,("ERROR: NULL dest in alpha_strcpy, called from [%s][%d]\n", fn, line));
722 return NULL;
723 }
724
725 if (!src) {
726 *dest = 0;
727 return dest;
728 }
729
730 len = strlen(src);
731 if (len >= maxlength)
732 len = maxlength - 1;
733
734 if (!other_safe_chars)
735 other_safe_chars = "";
736
737 for(i = 0; i < len; i++) {
738 int val = (src[i] & 0xff);
739 if (isupper_ascii(val) || islower_ascii(val) || isdigit(val) || strchr_m(other_safe_chars, val))
740 dest[i] = src[i];
741 else
742 dest[i] = '_';
743 }
744
745 dest[i] = '\0';
746
747 return dest;
748}
749
750/**
751 Like strncpy but always null terminates. Make sure there is room!
752 The variable n should always be one less than the available size.
753**/
754char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
755{
756 char *d = dest;
757
758#ifdef DEVELOPER
759 clobber_region(fn, line, dest, n+1);
760#endif
761
762 if (!dest) {
763 DEBUG(0,("ERROR: NULL dest in StrnCpy, called from [%s][%d]\n", fn, line));
764 return(NULL);
765 }
766
767 if (!src) {
768 *dest = 0;
769 return(dest);
770 }
771
772 while (n-- && (*d = *src)) {
773 d++;
774 src++;
775 }
776
777 *d = 0;
778 return(dest);
779}
780
781#if 0
782/**
783 Like strncpy but copies up to the character marker. always null terminates.
784 returns a pointer to the character marker in the source string (src).
785**/
786
787static char *strncpyn(char *dest, const char *src, size_t n, char c)
788{
789 char *p;
790 size_t str_len;
791
792#ifdef DEVELOPER
793 clobber_region(dest, n+1);
794#endif
795 p = strchr_m(src, c);
796 if (p == NULL) {
797 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
798 return NULL;
799 }
800
801 str_len = PTR_DIFF(p, src);
802 strncpy(dest, src, MIN(n, str_len));
803 dest[str_len] = '\0';
804
805 return p;
806}
807#endif
808
809/**
810 Routine to get hex characters and turn them into a 16 byte array.
811 the array can be variable length, and any non-hex-numeric
812 characters are skipped. "0xnn" or "0Xnn" is specially catered
813 for.
814
815 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
816
817**/
818
819size_t strhex_to_str(char *p, size_t len, const char *strhex)
820{
821 size_t i;
822 size_t num_chars = 0;
823 unsigned char lonybble, hinybble;
824 const char *hexchars = "0123456789ABCDEF";
825 char *p1 = NULL, *p2 = NULL;
826
827 for (i = 0; i < len && strhex[i] != 0; i++) {
828 if (strnequal(hexchars, "0x", 2)) {
829 i++; /* skip two chars */
830 continue;
831 }
832
833 if (!(p1 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
834 break;
835
836 i++; /* next hex digit */
837
838 if (!(p2 = strchr_m(hexchars, toupper_ascii(strhex[i]))))
839 break;
840
841 /* get the two nybbles */
842 hinybble = PTR_DIFF(p1, hexchars);
843 lonybble = PTR_DIFF(p2, hexchars);
844
845 p[num_chars] = (hinybble << 4) | lonybble;
846 num_chars++;
847
848 p1 = NULL;
849 p2 = NULL;
850 }
851 return num_chars;
852}
853
854DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
855{
856 DATA_BLOB ret_blob;
857
858 if (mem_ctx != NULL)
859 ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
860 else
861 ret_blob = data_blob(NULL, strlen(strhex)/2+1);
862
863 ret_blob.length = strhex_to_str((char*)ret_blob.data,
864 strlen(strhex),
865 strhex);
866
867 return ret_blob;
868}
869
870/**
871 * Routine to print a buffer as HEX digits, into an allocated string.
872 */
873
874char *hex_encode(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
875{
876 int i;
877 char *hex_buffer;
878
879 hex_buffer = TALLOC_ARRAY(mem_ctx, char, (len*2)+1);
880
881 for (i = 0; i < len; i++)
882 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
883
884 return hex_buffer;
885}
886
887/**
888 Check if a string is part of a list.
889**/
890
891BOOL in_list(const char *s, const char *list, BOOL casesensitive)
892{
893 pstring tok;
894 const char *p=list;
895
896 if (!list)
897 return(False);
898
899 while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
900 if (casesensitive) {
901 if (strcmp(tok,s) == 0)
902 return(True);
903 } else {
904 if (StrCaseCmp(tok,s) == 0)
905 return(True);
906 }
907 }
908 return(False);
909}
910
911/* this is used to prevent lots of mallocs of size 1 */
912static const char *null_string = "";
913
914/**
915 Set a string value, allocing the space for the string
916**/
917
918static BOOL string_init(char **dest,const char *src)
919{
920 size_t l;
921
922 if (!src)
923 src = "";
924
925 l = strlen(src);
926
927 if (l == 0) {
928 *dest = CONST_DISCARD(char*, null_string);
929 } else {
930 (*dest) = SMB_STRDUP(src);
931 if ((*dest) == NULL) {
932 DEBUG(0,("Out of memory in string_init\n"));
933 return False;
934 }
935 }
936 return(True);
937}
938
939/**
940 Free a string value.
941**/
942
943void string_free(char **s)
944{
945 if (!s || !(*s))
946 return;
947 if (*s == null_string)
948 *s = NULL;
949 SAFE_FREE(*s);
950}
951
952/**
953 Set a string value, deallocating any existing space, and allocing the space
954 for the string
955**/
956
957BOOL string_set(char **dest,const char *src)
958{
959 string_free(dest);
960 return(string_init(dest,src));
961}
962
963/**
964 Substitute a string for a pattern in another string. Make sure there is
965 enough room!
966
967 This routine looks for pattern in s and replaces it with
968 insert. It may do multiple replacements or just one.
969
970 Any of " ; ' $ or ` in the insert string are replaced with _
971 if len==0 then the string cannot be extended. This is different from the old
972 use of len==0 which was for no length checks to be done.
973**/
974
975void string_sub2(char *s,const char *pattern, const char *insert, size_t len,
976 BOOL remove_unsafe_characters, BOOL replace_once, BOOL allow_trailing_dollar)
977{
978 char *p;
979 ssize_t ls,lp,li, i;
980
981 if (!insert || !pattern || !*pattern || !s)
982 return;
983
984 ls = (ssize_t)strlen(s);
985 lp = (ssize_t)strlen(pattern);
986 li = (ssize_t)strlen(insert);
987
988 if (len == 0)
989 len = ls + 1; /* len is number of *bytes* */
990
991 while (lp <= ls && (p = strstr_m(s,pattern))) {
992 if (ls + (li-lp) >= len) {
993 DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n",
994 (int)(ls + (li-lp) - len),
995 pattern, (int)len));
996 break;
997 }
998 if (li != lp) {
999 memmove(p+li,p+lp,strlen(p+lp)+1);
1000 }
1001 for (i=0;i<li;i++) {
1002 switch (insert[i]) {
1003 case '`':
1004 case '"':
1005 case '\'':
1006 case ';':
1007 case '$':
1008 /* allow a trailing $ (as in machine accounts) */
1009 if (allow_trailing_dollar && (i == li - 1 )) {
1010 p[i] = insert[i];
1011 break;
1012 }
1013 case '%':
1014 case '\r':
1015 case '\n':
1016 if ( remove_unsafe_characters ) {
1017 p[i] = '_';
1018 /* yes this break should be here since we want to
1019 fall throw if not replacing unsafe chars */
1020 break;
1021 }
1022 default:
1023 p[i] = insert[i];
1024 }
1025 }
1026 s = p + li;
1027 ls += (li-lp);
1028
1029 if (replace_once)
1030 break;
1031 }
1032}
1033
1034void string_sub_once(char *s, const char *pattern, const char *insert, size_t len)
1035{
1036 string_sub2( s, pattern, insert, len, True, True, False );
1037}
1038
1039void string_sub(char *s,const char *pattern, const char *insert, size_t len)
1040{
1041 string_sub2( s, pattern, insert, len, True, False, False );
1042}
1043
1044void fstring_sub(char *s,const char *pattern,const char *insert)
1045{
1046 string_sub(s, pattern, insert, sizeof(fstring));
1047}
1048
1049void pstring_sub(char *s,const char *pattern,const char *insert)
1050{
1051 string_sub(s, pattern, insert, sizeof(pstring));
1052}
1053
1054/**
1055 Similar to string_sub, but it will accept only allocated strings
1056 and may realloc them so pay attention at what you pass on no
1057 pointers inside strings, no pstrings or const may be passed
1058 as string.
1059**/
1060
1061char *realloc_string_sub(char *string, const char *pattern,
1062 const char *insert)
1063{
1064 char *p, *in;
1065 char *s;
1066 ssize_t ls,lp,li,ld, i;
1067
1068 if (!insert || !pattern || !*pattern || !string || !*string)
1069 return NULL;
1070
1071 s = string;
1072
1073 in = SMB_STRDUP(insert);
1074 if (!in) {
1075 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1076 return NULL;
1077 }
1078 ls = (ssize_t)strlen(s);
1079 lp = (ssize_t)strlen(pattern);
1080 li = (ssize_t)strlen(insert);
1081 ld = li - lp;
1082 for (i=0;i<li;i++) {
1083 switch (in[i]) {
1084 case '`':
1085 case '"':
1086 case '\'':
1087 case ';':
1088 case '$':
1089 case '%':
1090 case '\r':
1091 case '\n':
1092 in[i] = '_';
1093 default:
1094 /* ok */
1095 break;
1096 }
1097 }
1098
1099 while ((p = strstr_m(s,pattern))) {
1100 if (ld > 0) {
1101 int offset = PTR_DIFF(s,string);
1102 string = (char *)SMB_REALLOC(string, ls + ld + 1);
1103 if (!string) {
1104 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1105 SAFE_FREE(in);
1106 return NULL;
1107 }
1108 p = string + offset + (p - s);
1109 }
1110 if (li != lp) {
1111 memmove(p+li,p+lp,strlen(p+lp)+1);
1112 }
1113 memcpy(p, in, li);
1114 s = p + li;
1115 ls += ld;
1116 }
1117 SAFE_FREE(in);
1118 return string;
1119}
1120
1121/* Same as string_sub, but returns a talloc'ed string */
1122
1123char *talloc_string_sub(TALLOC_CTX *mem_ctx, const char *src,
1124 const char *pattern, const char *insert)
1125{
1126 char *p, *in;
1127 char *s;
1128 char *string;
1129 ssize_t ls,lp,li,ld, i;
1130
1131 if (!insert || !pattern || !*pattern || !src || !*src)
1132 return NULL;
1133
1134 string = talloc_strdup(mem_ctx, src);
1135 if (string == NULL) {
1136 DEBUG(0, ("talloc_strdup failed\n"));
1137 return NULL;
1138 }
1139
1140 s = string;
1141
1142 in = SMB_STRDUP(insert);
1143 if (!in) {
1144 DEBUG(0, ("talloc_string_sub: out of memory!\n"));
1145 return NULL;
1146 }
1147 ls = (ssize_t)strlen(s);
1148 lp = (ssize_t)strlen(pattern);
1149 li = (ssize_t)strlen(insert);
1150 ld = li - lp;
1151 for (i=0;i<li;i++) {
1152 switch (in[i]) {
1153 case '`':
1154 case '"':
1155 case '\'':
1156 case ';':
1157 case '$':
1158 case '%':
1159 case '\r':
1160 case '\n':
1161 in[i] = '_';
1162 default:
1163 /* ok */
1164 break;
1165 }
1166 }
1167
1168 while ((p = strstr_m(s,pattern))) {
1169 if (ld > 0) {
1170 int offset = PTR_DIFF(s,string);
1171 string = (char *)TALLOC_REALLOC(mem_ctx, string,
1172 ls + ld + 1);
1173 if (!string) {
1174 DEBUG(0, ("talloc_string_sub: out of "
1175 "memory!\n"));
1176 SAFE_FREE(in);
1177 return NULL;
1178 }
1179 p = string + offset + (p - s);
1180 }
1181 if (li != lp) {
1182 memmove(p+li,p+lp,strlen(p+lp)+1);
1183 }
1184 memcpy(p, in, li);
1185 s = p + li;
1186 ls += ld;
1187 }
1188 SAFE_FREE(in);
1189 return string;
1190}
1191
1192/**
1193 Similar to string_sub() but allows for any character to be substituted.
1194 Use with caution!
1195 if len==0 then the string cannot be extended. This is different from the old
1196 use of len==0 which was for no length checks to be done.
1197**/
1198
1199void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1200{
1201 char *p;
1202 ssize_t ls,lp,li;
1203
1204 if (!insert || !pattern || !s)
1205 return;
1206
1207 ls = (ssize_t)strlen(s);
1208 lp = (ssize_t)strlen(pattern);
1209 li = (ssize_t)strlen(insert);
1210
1211 if (!*pattern)
1212 return;
1213
1214 if (len == 0)
1215 len = ls + 1; /* len is number of *bytes* */
1216
1217 while (lp <= ls && (p = strstr_m(s,pattern))) {
1218 if (ls + (li-lp) >= len) {
1219 DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n",
1220 (int)(ls + (li-lp) - len),
1221 pattern, (int)len));
1222 break;
1223 }
1224 if (li != lp) {
1225 memmove(p+li,p+lp,strlen(p+lp)+1);
1226 }
1227 memcpy(p, insert, li);
1228 s = p + li;
1229 ls += (li-lp);
1230 }
1231}
1232
1233/**
1234 Similar to all_string_sub but for unicode strings.
1235 Return a new allocated unicode string.
1236 similar to string_sub() but allows for any character to be substituted.
1237 Use with caution!
1238**/
1239
1240static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
1241 const smb_ucs2_t *insert)
1242{
1243 smb_ucs2_t *r, *rp;
1244 const smb_ucs2_t *sp;
1245 size_t lr, lp, li, lt;
1246
1247 if (!insert || !pattern || !*pattern || !s)
1248 return NULL;
1249
1250 lt = (size_t)strlen_w(s);
1251 lp = (size_t)strlen_w(pattern);
1252 li = (size_t)strlen_w(insert);
1253
1254 if (li > lp) {
1255 const smb_ucs2_t *st = s;
1256 int ld = li - lp;
1257 while ((sp = strstr_w(st, pattern))) {
1258 st = sp + lp;
1259 lt += ld;
1260 }
1261 }
1262
1263 r = rp = SMB_MALLOC_ARRAY(smb_ucs2_t, lt + 1);
1264 if (!r) {
1265 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
1266 return NULL;
1267 }
1268
1269 while ((sp = strstr_w(s, pattern))) {
1270 memcpy(rp, s, (sp - s));
1271 rp += ((sp - s) / sizeof(smb_ucs2_t));
1272 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
1273 s = sp + lp;
1274 rp += li;
1275 }
1276 lr = ((rp - r) / sizeof(smb_ucs2_t));
1277 if (lr < lt) {
1278 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
1279 rp += (lt - lr);
1280 }
1281 *rp = 0;
1282
1283 return r;
1284}
1285
1286smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
1287 const char *insert)
1288{
1289 wpstring p, i;
1290
1291 if (!insert || !pattern || !s)
1292 return NULL;
1293 push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1294 push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1295 return all_string_sub_w(s, p, i);
1296}
1297
1298#if 0
1299/**
1300 Splits out the front and back at a separator.
1301**/
1302
1303static void split_at_last_component(char *path, char *front, char sep, char *back)
1304{
1305 char *p = strrchr_m(path, sep);
1306
1307 if (p != NULL)
1308 *p = 0;
1309
1310 if (front != NULL)
1311 pstrcpy(front, path);
1312
1313 if (p != NULL) {
1314 if (back != NULL)
1315 pstrcpy(back, p+1);
1316 *p = '\\';
1317 } else {
1318 if (back != NULL)
1319 back[0] = 0;
1320 }
1321}
1322#endif
1323
1324/**
1325 Write an octal as a string.
1326**/
1327
1328const char *octal_string(int i)
1329{
1330 static char ret[64];
1331 if (i == -1)
1332 return "-1";
1333 slprintf(ret, sizeof(ret)-1, "0%o", i);
1334 return ret;
1335}
1336
1337
1338/**
1339 Truncate a string at a specified length.
1340**/
1341
1342char *string_truncate(char *s, unsigned int length)
1343{
1344 if (s && strlen(s) > length)
1345 s[length] = 0;
1346 return s;
1347}
1348
1349/**
1350 Strchr and strrchr_m are very hard to do on general multi-byte strings.
1351 We convert via ucs2 for now.
1352**/
1353
1354char *strchr_m(const char *src, char c)
1355{
1356 wpstring ws;
1357 pstring s2;
1358 smb_ucs2_t *p;
1359 const char *s;
1360
1361 /* characters below 0x3F are guaranteed to not appear in
1362 non-initial position in multi-byte charsets */
1363 if ((c & 0xC0) == 0) {
1364 return strchr(src, c);
1365 }
1366
1367 /* this is quite a common operation, so we want it to be
1368 fast. We optimise for the ascii case, knowing that all our
1369 supported multi-byte character sets are ascii-compatible
1370 (ie. they match for the first 128 chars) */
1371
1372 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1373 if (*s == c)
1374 return (char *)s;
1375 }
1376
1377 if (!*s)
1378 return NULL;
1379
1380#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1381 /* With compose characters we must restart from the beginning. JRA. */
1382 s = src;
1383#endif
1384
1385 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1386 p = strchr_w(ws, UCS2_CHAR(c));
1387 if (!p)
1388 return NULL;
1389 *p = 0;
1390 pull_ucs2_pstring(s2, ws);
1391 return (char *)(s+strlen(s2));
1392}
1393
1394char *strrchr_m(const char *s, char c)
1395{
1396 /* characters below 0x3F are guaranteed to not appear in
1397 non-initial position in multi-byte charsets */
1398 if ((c & 0xC0) == 0) {
1399 return strrchr(s, c);
1400 }
1401
1402 /* this is quite a common operation, so we want it to be
1403 fast. We optimise for the ascii case, knowing that all our
1404 supported multi-byte character sets are ascii-compatible
1405 (ie. they match for the first 128 chars). Also, in Samba
1406 we only search for ascii characters in 'c' and that
1407 in all mb character sets with a compound character
1408 containing c, if 'c' is not a match at position
1409 p, then p[-1] > 0x7f. JRA. */
1410
1411 {
1412 size_t len = strlen(s);
1413 const char *cp = s;
1414 BOOL got_mb = False;
1415
1416 if (len == 0)
1417 return NULL;
1418 cp += (len - 1);
1419 do {
1420 if (c == *cp) {
1421 /* Could be a match. Part of a multibyte ? */
1422 if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
1423 /* Yep - go slow :-( */
1424 got_mb = True;
1425 break;
1426 }
1427 /* No - we have a match ! */
1428 return (char *)cp;
1429 }
1430 } while (cp-- != s);
1431 if (!got_mb)
1432 return NULL;
1433 }
1434
1435 /* String contained a non-ascii char. Slow path. */
1436 {
1437 wpstring ws;
1438 pstring s2;
1439 smb_ucs2_t *p;
1440
1441 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1442 p = strrchr_w(ws, UCS2_CHAR(c));
1443 if (!p)
1444 return NULL;
1445 *p = 0;
1446 pull_ucs2_pstring(s2, ws);
1447 return (char *)(s+strlen(s2));
1448 }
1449}
1450
1451/***********************************************************************
1452 Return the equivalent of doing strrchr 'n' times - always going
1453 backwards.
1454***********************************************************************/
1455
1456char *strnrchr_m(const char *s, char c, unsigned int n)
1457{
1458 wpstring ws;
1459 pstring s2;
1460 smb_ucs2_t *p;
1461
1462 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1463 p = strnrchr_w(ws, UCS2_CHAR(c), n);
1464 if (!p)
1465 return NULL;
1466 *p = 0;
1467 pull_ucs2_pstring(s2, ws);
1468 return (char *)(s+strlen(s2));
1469}
1470
1471/***********************************************************************
1472 strstr_m - We convert via ucs2 for now.
1473***********************************************************************/
1474
1475char *strstr_m(const char *src, const char *findstr)
1476{
1477 smb_ucs2_t *p;
1478 smb_ucs2_t *src_w, *find_w;
1479 const char *s;
1480 char *s2;
1481 char *retp;
1482
1483 size_t findstr_len = 0;
1484
1485 /* for correctness */
1486 if (!findstr[0]) {
1487 return (char*)src;
1488 }
1489
1490 /* Samba does single character findstr calls a *lot*. */
1491 if (findstr[1] == '\0')
1492 return strchr_m(src, *findstr);
1493
1494 /* We optimise for the ascii case, knowing that all our
1495 supported multi-byte character sets are ascii-compatible
1496 (ie. they match for the first 128 chars) */
1497
1498 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1499 if (*s == *findstr) {
1500 if (!findstr_len)
1501 findstr_len = strlen(findstr);
1502
1503 if (strncmp(s, findstr, findstr_len) == 0) {
1504 return (char *)s;
1505 }
1506 }
1507 }
1508
1509 if (!*s)
1510 return NULL;
1511
1512#if 1 /* def BROKEN_UNICODE_COMPOSE_CHARACTERS */
1513 /* 'make check' fails unless we do this */
1514
1515 /* With compose characters we must restart from the beginning. JRA. */
1516 s = src;
1517#endif
1518
1519 if (push_ucs2_allocate(&src_w, src) == (size_t)-1) {
1520 DEBUG(0,("strstr_m: src malloc fail\n"));
1521 return NULL;
1522 }
1523
1524 if (push_ucs2_allocate(&find_w, findstr) == (size_t)-1) {
1525 SAFE_FREE(src_w);
1526 DEBUG(0,("strstr_m: find malloc fail\n"));
1527 return NULL;
1528 }
1529
1530 p = strstr_w(src_w, find_w);
1531
1532 if (!p) {
1533 SAFE_FREE(src_w);
1534 SAFE_FREE(find_w);
1535 return NULL;
1536 }
1537
1538 *p = 0;
1539 if (pull_ucs2_allocate(&s2, src_w) == (size_t)-1) {
1540 SAFE_FREE(src_w);
1541 SAFE_FREE(find_w);
1542 DEBUG(0,("strstr_m: dest malloc fail\n"));
1543 return NULL;
1544 }
1545 retp = (char *)(s+strlen(s2));
1546 SAFE_FREE(src_w);
1547 SAFE_FREE(find_w);
1548 SAFE_FREE(s2);
1549 return retp;
1550}
1551
1552/**
1553 Convert a string to lower case.
1554**/
1555
1556void strlower_m(char *s)
1557{
1558 size_t len;
1559 int errno_save;
1560
1561 /* this is quite a common operation, so we want it to be
1562 fast. We optimise for the ascii case, knowing that all our
1563 supported multi-byte character sets are ascii-compatible
1564 (ie. they match for the first 128 chars) */
1565
1566 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1567 *s = tolower_ascii((unsigned char)*s);
1568 s++;
1569 }
1570
1571 if (!*s)
1572 return;
1573
1574 /* I assume that lowercased string takes the same number of bytes
1575 * as source string even in UTF-8 encoding. (VIV) */
1576 len = strlen(s) + 1;
1577 errno_save = errno;
1578 errno = 0;
1579 unix_strlower(s,len,s,len);
1580 /* Catch mb conversion errors that may not terminate. */
1581 if (errno)
1582 s[len-1] = '\0';
1583 errno = errno_save;
1584}
1585
1586/**
1587 Convert a string to upper case.
1588**/
1589
1590void strupper_m(char *s)
1591{
1592 size_t len;
1593 int errno_save;
1594
1595 /* this is quite a common operation, so we want it to be
1596 fast. We optimise for the ascii case, knowing that all our
1597 supported multi-byte character sets are ascii-compatible
1598 (ie. they match for the first 128 chars) */
1599
1600 while (*s && !(((unsigned char)s[0]) & 0x80)) {
1601 *s = toupper_ascii((unsigned char)*s);
1602 s++;
1603 }
1604
1605 if (!*s)
1606 return;
1607
1608 /* I assume that lowercased string takes the same number of bytes
1609 * as source string even in multibyte encoding. (VIV) */
1610 len = strlen(s) + 1;
1611 errno_save = errno;
1612 errno = 0;
1613 unix_strupper(s,len,s,len);
1614 /* Catch mb conversion errors that may not terminate. */
1615 if (errno)
1616 s[len-1] = '\0';
1617 errno = errno_save;
1618}
1619
1620/**
1621 Count the number of UCS2 characters in a string. Normally this will
1622 be the same as the number of bytes in a string for single byte strings,
1623 but will be different for multibyte.
1624**/
1625
1626size_t strlen_m(const char *s)
1627{
1628 size_t count = 0;
1629
1630 if (!s) {
1631 return 0;
1632 }
1633
1634 while (*s && !(((uint8_t)*s) & 0x80)) {
1635 s++;
1636 count++;
1637 }
1638
1639 if (!*s) {
1640 return count;
1641 }
1642
1643 while (*s) {
1644 size_t c_size;
1645 codepoint_t c = next_codepoint(s, &c_size);
1646 if (c < 0x10000) {
1647 /* Unicode char fits into 16 bits. */
1648 count += 1;
1649 } else {
1650 /* Double-width unicode char - 32 bits. */
1651 count += 2;
1652 }
1653 s += c_size;
1654 }
1655
1656 return count;
1657}
1658
1659/**
1660 Count the number of UCS2 characters in a string including the null
1661 terminator.
1662**/
1663
1664size_t strlen_m_term(const char *s)
1665{
1666 if (!s) {
1667 return 0;
1668 }
1669 return strlen_m(s) + 1;
1670}
1671
1672/*
1673 * Weird helper routine for the winreg pipe: If nothing is around, return 0,
1674 * if a string is there, include the terminator.
1675 */
1676
1677size_t strlen_m_term_null(const char *s)
1678{
1679 size_t len;
1680 if (!s) {
1681 return 0;
1682 }
1683 len = strlen_m(s);
1684 if (len == 0) {
1685 return 0;
1686 }
1687
1688 return len+1;
1689}
1690/**
1691 Return a RFC2254 binary string representation of a buffer.
1692 Used in LDAP filters.
1693 Caller must free.
1694**/
1695
1696char *binary_string_rfc2254(char *buf, int len)
1697{
1698 char *s;
1699 int i, j;
1700 const char *hex = "0123456789ABCDEF";
1701 s = (char *)SMB_MALLOC(len * 3 + 1);
1702 if (!s)
1703 return NULL;
1704 for (j=i=0;i<len;i++) {
1705 s[j] = '\\';
1706 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1707 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1708 j += 3;
1709 }
1710 s[j] = 0;
1711 return s;
1712}
1713
1714char *binary_string(char *buf, int len)
1715{
1716 char *s;
1717 int i, j;
1718 const char *hex = "0123456789ABCDEF";
1719 s = (char *)SMB_MALLOC(len * 2 + 1);
1720 if (!s)
1721 return NULL;
1722 for (j=i=0;i<len;i++) {
1723 s[j] = hex[((unsigned char)buf[i]) >> 4];
1724 s[j+1] = hex[((unsigned char)buf[i]) & 0xF];
1725 j += 2;
1726 }
1727 s[j] = 0;
1728 return s;
1729}
1730/**
1731 Just a typesafety wrapper for snprintf into a pstring.
1732**/
1733
1734 int pstr_sprintf(pstring s, const char *fmt, ...)
1735{
1736 va_list ap;
1737 int ret;
1738
1739 va_start(ap, fmt);
1740 ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1741 va_end(ap);
1742 return ret;
1743}
1744
1745
1746/**
1747 Just a typesafety wrapper for snprintf into a fstring.
1748**/
1749
1750int fstr_sprintf(fstring s, const char *fmt, ...)
1751{
1752 va_list ap;
1753 int ret;
1754
1755 va_start(ap, fmt);
1756 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1757 va_end(ap);
1758 return ret;
1759}
1760
1761/**
1762 List of Strings manipulation functions
1763**/
1764
1765#define S_LIST_ABS 16 /* List Allocation Block Size */
1766
1767static char **str_list_make_internal(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
1768{
1769 char **list, **rlist;
1770 const char *str;
1771 char *s;
1772 int num, lsize;
1773 pstring tok;
1774
1775 if (!string || !*string)
1776 return NULL;
1777 if (mem_ctx) {
1778 s = talloc_strdup(mem_ctx, string);
1779 } else {
1780 s = SMB_STRDUP(string);
1781 }
1782 if (!s) {
1783 DEBUG(0,("str_list_make: Unable to allocate memory"));
1784 return NULL;
1785 }
1786 if (!sep) sep = LIST_SEP;
1787
1788 num = lsize = 0;
1789 list = NULL;
1790
1791 str = s;
1792 while (next_token(&str, tok, sep, sizeof(tok))) {
1793 if (num == lsize) {
1794 lsize += S_LIST_ABS;
1795 if (mem_ctx) {
1796 rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *, lsize +1);
1797 } else {
1798 /* We need to keep the old list on error so we can free the elements
1799 if the realloc fails. */
1800 rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, char *, lsize +1);
1801 }
1802 if (!rlist) {
1803 DEBUG(0,("str_list_make: Unable to allocate memory"));
1804 str_list_free(&list);
1805 if (mem_ctx) {
1806 TALLOC_FREE(s);
1807 } else {
1808 SAFE_FREE(s);
1809 }
1810 return NULL;
1811 } else {
1812 list = rlist;
1813 }
1814 memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1815 }
1816
1817 if (mem_ctx) {
1818 list[num] = talloc_strdup(mem_ctx, tok);
1819 } else {
1820 list[num] = SMB_STRDUP(tok);
1821 }
1822
1823 if (!list[num]) {
1824 DEBUG(0,("str_list_make: Unable to allocate memory"));
1825 str_list_free(&list);
1826 if (mem_ctx) {
1827 TALLOC_FREE(s);
1828 } else {
1829 SAFE_FREE(s);
1830 }
1831 return NULL;
1832 }
1833
1834 num++;
1835 }
1836
1837 if (mem_ctx) {
1838 TALLOC_FREE(s);
1839 } else {
1840 SAFE_FREE(s);
1841 }
1842
1843 return list;
1844}
1845
1846char **str_list_make_talloc(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
1847{
1848 return str_list_make_internal(mem_ctx, string, sep);
1849}
1850
1851char **str_list_make(const char *string, const char *sep)
1852{
1853 return str_list_make_internal(NULL, string, sep);
1854}
1855
1856BOOL str_list_copy(char ***dest, const char **src)
1857{
1858 char **list, **rlist;
1859 int num, lsize;
1860
1861 *dest = NULL;
1862 if (!src)
1863 return False;
1864
1865 num = lsize = 0;
1866 list = NULL;
1867
1868 while (src[num]) {
1869 if (num == lsize) {
1870 lsize += S_LIST_ABS;
1871 rlist = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(list, char *, lsize +1);
1872 if (!rlist) {
1873 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1874 str_list_free(&list);
1875 return False;
1876 } else {
1877 list = rlist;
1878 }
1879 memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1880 }
1881
1882 list[num] = SMB_STRDUP(src[num]);
1883 if (!list[num]) {
1884 DEBUG(0,("str_list_copy: Unable to allocate memory"));
1885 str_list_free(&list);
1886 return False;
1887 }
1888
1889 num++;
1890 }
1891
1892 *dest = list;
1893 return True;
1894}
1895
1896/**
1897 * Return true if all the elements of the list match exactly.
1898 **/
1899BOOL str_list_compare(char **list1, char **list2)
1900{
1901 int num;
1902
1903 if (!list1 || !list2)
1904 return (list1 == list2);
1905
1906 for (num = 0; list1[num]; num++) {
1907 if (!list2[num])
1908 return False;
1909 if (!strcsequal(list1[num], list2[num]))
1910 return False;
1911 }
1912 if (list2[num])
1913 return False; /* if list2 has more elements than list1 fail */
1914
1915 return True;
1916}
1917
1918static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list)
1919{
1920 char **tlist;
1921
1922 if (!list || !*list)
1923 return;
1924 tlist = *list;
1925 for(; *tlist; tlist++) {
1926 if (mem_ctx) {
1927 TALLOC_FREE(*tlist);
1928 } else {
1929 SAFE_FREE(*tlist);
1930 }
1931 }
1932 if (mem_ctx) {
1933 TALLOC_FREE(*tlist);
1934 } else {
1935 SAFE_FREE(*list);
1936 }
1937}
1938
1939void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list)
1940{
1941 str_list_free_internal(mem_ctx, list);
1942}
1943
1944void str_list_free(char ***list)
1945{
1946 str_list_free_internal(NULL, list);
1947}
1948
1949/******************************************************************************
1950 *****************************************************************************/
1951
1952int str_list_count( const char **list )
1953{
1954 int i = 0;
1955
1956 if ( ! list )
1957 return 0;
1958
1959 /* count the number of list members */
1960
1961 for ( i=0; *list; i++, list++ );
1962
1963 return i;
1964}
1965
1966/******************************************************************************
1967 version of standard_sub_basic() for string lists; uses alloc_sub_basic()
1968 for the work
1969 *****************************************************************************/
1970
1971BOOL str_list_sub_basic( char **list, const char *smb_name,
1972 const char *domain_name )
1973{
1974 char *s, *tmpstr;
1975
1976 while ( *list ) {
1977 s = *list;
1978 tmpstr = alloc_sub_basic(smb_name, domain_name, s);
1979 if ( !tmpstr ) {
1980 DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
1981 return False;
1982 }
1983
1984 SAFE_FREE(*list);
1985 *list = tmpstr;
1986
1987 list++;
1988 }
1989
1990 return True;
1991}
1992
1993/******************************************************************************
1994 substritute a specific pattern in a string list
1995 *****************************************************************************/
1996
1997BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1998{
1999 char *p, *s, *t;
2000 ssize_t ls, lp, li, ld, i, d;
2001
2002 if (!list)
2003 return False;
2004 if (!pattern)
2005 return False;
2006 if (!insert)
2007 return False;
2008
2009 lp = (ssize_t)strlen(pattern);
2010 li = (ssize_t)strlen(insert);
2011 ld = li -lp;
2012
2013 while (*list) {
2014 s = *list;
2015 ls = (ssize_t)strlen(s);
2016
2017 while ((p = strstr_m(s, pattern))) {
2018 t = *list;
2019 d = p -t;
2020 if (ld) {
2021 t = (char *) SMB_MALLOC(ls +ld +1);
2022 if (!t) {
2023 DEBUG(0,("str_list_substitute: Unable to allocate memory"));
2024 return False;
2025 }
2026 memcpy(t, *list, d);
2027 memcpy(t +d +li, p +lp, ls -d -lp +1);
2028 SAFE_FREE(*list);
2029 *list = t;
2030 ls += ld;
2031 s = t +d +li;
2032 }
2033
2034 for (i = 0; i < li; i++) {
2035 switch (insert[i]) {
2036 case '`':
2037 case '"':
2038 case '\'':
2039 case ';':
2040 case '$':
2041 case '%':
2042 case '\r':
2043 case '\n':
2044 t[d +i] = '_';
2045 break;
2046 default:
2047 t[d +i] = insert[i];
2048 }
2049 }
2050 }
2051
2052
2053 list++;
2054 }
2055
2056 return True;
2057}
2058
2059
2060#define IPSTR_LIST_SEP ","
2061#define IPSTR_LIST_CHAR ','
2062
2063/**
2064 * Add ip string representation to ipstr list. Used also
2065 * as part of @function ipstr_list_make
2066 *
2067 * @param ipstr_list pointer to string containing ip list;
2068 * MUST BE already allocated and IS reallocated if necessary
2069 * @param ipstr_size pointer to current size of ipstr_list (might be changed
2070 * as a result of reallocation)
2071 * @param ip IP address which is to be added to list
2072 * @return pointer to string appended with new ip and possibly
2073 * reallocated to new length
2074 **/
2075
2076char* ipstr_list_add(char** ipstr_list, const struct ip_service *service)
2077{
2078 char* new_ipstr = NULL;
2079
2080 /* arguments checking */
2081 if (!ipstr_list || !service) return NULL;
2082
2083 /* attempt to convert ip to a string and append colon separator to it */
2084 if (*ipstr_list) {
2085 asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP,
2086 inet_ntoa(service->ip), service->port);
2087 SAFE_FREE(*ipstr_list);
2088 } else {
2089 asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port);
2090 }
2091 *ipstr_list = new_ipstr;
2092 return *ipstr_list;
2093}
2094
2095
2096/**
2097 * Allocate and initialise an ipstr list using ip adresses
2098 * passed as arguments.
2099 *
2100 * @param ipstr_list pointer to string meant to be allocated and set
2101 * @param ip_list array of ip addresses to place in the list
2102 * @param ip_count number of addresses stored in ip_list
2103 * @return pointer to allocated ip string
2104 **/
2105
2106char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count)
2107{
2108 int i;
2109
2110 /* arguments checking */
2111 if (!ip_list || !ipstr_list) return 0;
2112
2113 *ipstr_list = NULL;
2114
2115 /* process ip addresses given as arguments */
2116 for (i = 0; i < ip_count; i++)
2117 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
2118
2119 return (*ipstr_list);
2120}
2121
2122
2123/**
2124 * Parse given ip string list into array of ip addresses
2125 * (as ip_service structures)
2126 * e.g. 192.168.1.100:389,192.168.1.78, ...
2127 *
2128 * @param ipstr ip string list to be parsed
2129 * @param ip_list pointer to array of ip addresses which is
2130 * allocated by this function and must be freed by caller
2131 * @return number of succesfully parsed addresses
2132 **/
2133
2134int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list)
2135{
2136 fstring token_str;
2137 size_t count;
2138 int i;
2139
2140 if (!ipstr_list || !ip_list)
2141 return 0;
2142
2143 count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
2144 if ( (*ip_list = SMB_MALLOC_ARRAY(struct ip_service, count)) == NULL ) {
2145 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count));
2146 return 0;
2147 }
2148
2149 for ( i=0;
2150 next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count;
2151 i++ )
2152 {
2153 struct in_addr addr;
2154 unsigned port = 0;
2155 char *p = strchr(token_str, ':');
2156
2157 if (p) {
2158 *p = 0;
2159 port = atoi(p+1);
2160 }
2161
2162 /* convert single token to ip address */
2163 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
2164 break;
2165
2166 (*ip_list)[i].ip = addr;
2167 (*ip_list)[i].port = port;
2168 }
2169
2170 return count;
2171}
2172
2173
2174/**
2175 * Safely free ip string list
2176 *
2177 * @param ipstr_list ip string list to be freed
2178 **/
2179
2180void ipstr_list_free(char* ipstr_list)
2181{
2182 SAFE_FREE(ipstr_list);
2183}
2184
2185
2186/**
2187 Unescape a URL encoded string, in place.
2188**/
2189
2190void rfc1738_unescape(char *buf)
2191{
2192 char *p=buf;
2193
2194 while (p && *p && (p=strchr_m(p,'%'))) {
2195 int c1 = p[1];
2196 int c2 = p[2];
2197
2198 if (c1 >= '0' && c1 <= '9')
2199 c1 = c1 - '0';
2200 else if (c1 >= 'A' && c1 <= 'F')
2201 c1 = 10 + c1 - 'A';
2202 else if (c1 >= 'a' && c1 <= 'f')
2203 c1 = 10 + c1 - 'a';
2204 else {p++; continue;}
2205
2206 if (c2 >= '0' && c2 <= '9')
2207 c2 = c2 - '0';
2208 else if (c2 >= 'A' && c2 <= 'F')
2209 c2 = 10 + c2 - 'A';
2210 else if (c2 >= 'a' && c2 <= 'f')
2211 c2 = 10 + c2 - 'a';
2212 else {p++; continue;}
2213
2214 *p = (c1<<4) | c2;
2215
2216 memmove(p+1, p+3, strlen(p+3)+1);
2217 p++;
2218 }
2219}
2220
2221static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2222
2223/**
2224 * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
2225 **/
2226DATA_BLOB base64_decode_data_blob(const char *s)
2227{
2228 int bit_offset, byte_offset, idx, i, n;
2229 DATA_BLOB decoded = data_blob(s, strlen(s)+1);
2230 unsigned char *d = decoded.data;
2231 char *p;
2232
2233 n=i=0;
2234
2235 while (*s && (p=strchr_m(b64,*s))) {
2236 idx = (int)(p - b64);
2237 byte_offset = (i*6)/8;
2238 bit_offset = (i*6)%8;
2239 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
2240 if (bit_offset < 3) {
2241 d[byte_offset] |= (idx << (2-bit_offset));
2242 n = byte_offset+1;
2243 } else {
2244 d[byte_offset] |= (idx >> (bit_offset-2));
2245 d[byte_offset+1] = 0;
2246 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
2247 n = byte_offset+2;
2248 }
2249 s++; i++;
2250 }
2251
2252 if ((n > 0) && (*s == '=')) {
2253 n -= 1;
2254 }
2255
2256 /* fix up length */
2257 decoded.length = n;
2258 return decoded;
2259}
2260
2261/**
2262 * Decode a base64 string in-place - wrapper for the above
2263 **/
2264void base64_decode_inplace(char *s)
2265{
2266 DATA_BLOB decoded = base64_decode_data_blob(s);
2267
2268 if ( decoded.length != 0 ) {
2269 memcpy(s, decoded.data, decoded.length);
2270
2271 /* null terminate */
2272 s[decoded.length] = '\0';
2273 } else {
2274 *s = '\0';
2275 }
2276
2277 data_blob_free(&decoded);
2278}
2279
2280/**
2281 * Encode a base64 string into a malloc()ed string caller to free.
2282 *
2283 *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
2284 **/
2285char * base64_encode_data_blob(DATA_BLOB data)
2286{
2287 int bits = 0;
2288 int char_count = 0;
2289 size_t out_cnt, len, output_len;
2290 char *result;
2291
2292 if (!data.length || !data.data)
2293 return NULL;
2294
2295 out_cnt = 0;
2296 len = data.length;
2297 output_len = data.length * 2;
2298 result = (char *)SMB_MALLOC(output_len); /* get us plenty of space */
2299
2300 while (len-- && out_cnt < (data.length * 2) - 5) {
2301 int c = (unsigned char) *(data.data++);
2302 bits += c;
2303 char_count++;
2304 if (char_count == 3) {
2305 result[out_cnt++] = b64[bits >> 18];
2306 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2307 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2308 result[out_cnt++] = b64[bits & 0x3f];
2309 bits = 0;
2310 char_count = 0;
2311 } else {
2312 bits <<= 8;
2313 }
2314 }
2315 if (char_count != 0) {
2316 bits <<= 16 - (8 * char_count);
2317 result[out_cnt++] = b64[bits >> 18];
2318 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
2319 if (char_count == 1) {
2320 result[out_cnt++] = '=';
2321 result[out_cnt++] = '=';
2322 } else {
2323 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
2324 result[out_cnt++] = '=';
2325 }
2326 }
2327 result[out_cnt] = '\0'; /* terminate */
2328 return result;
2329}
2330
2331/* read a SMB_BIG_UINT from a string */
2332SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
2333{
2334
2335 SMB_BIG_UINT val = -1;
2336 const char *p = nptr;
2337
2338 if (!p) {
2339 if (entptr) {
2340 *entptr = p;
2341 }
2342 return val;
2343 }
2344
2345 while (*p && isspace(*p))
2346 p++;
2347
2348#ifdef LARGE_SMB_OFF_T
2349 sscanf(p,"%llu",&val);
2350#else /* LARGE_SMB_OFF_T */
2351 sscanf(p,"%lu",&val);
2352#endif /* LARGE_SMB_OFF_T */
2353 if (entptr) {
2354 while (*p && isdigit(*p))
2355 p++;
2356 *entptr = p;
2357 }
2358
2359 return val;
2360}
2361
2362/* Convert a size specification to a count of bytes. We accept the following
2363 * suffixes:
2364 * bytes if there is no suffix
2365 * kK kibibytes
2366 * mM mebibytes
2367 * gG gibibytes
2368 * tT tibibytes
2369 * pP whatever the ISO name for petabytes is
2370 *
2371 * Returns 0 if the string can't be converted.
2372 */
2373SMB_OFF_T conv_str_size(const char * str)
2374{
2375 SMB_OFF_T lval;
2376 char * end;
2377
2378 if (str == NULL || *str == '\0') {
2379 return 0;
2380 }
2381
2382#ifdef HAVE_STRTOULL
2383 if (sizeof(SMB_OFF_T) == 8) {
2384 lval = strtoull(str, &end, 10 /* base */);
2385 } else {
2386 lval = strtoul(str, &end, 10 /* base */);
2387 }
2388#else
2389 lval = strtoul(str, &end, 10 /* base */);
2390#endif
2391
2392 if (end == NULL || end == str) {
2393 return 0;
2394 }
2395
2396 if (*end) {
2397 SMB_OFF_T lval_orig = lval;
2398
2399 if (strwicmp(end, "K") == 0) {
2400 lval *= (SMB_OFF_T)1024;
2401 } else if (strwicmp(end, "M") == 0) {
2402 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2403 } else if (strwicmp(end, "G") == 0) {
2404 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2405 (SMB_OFF_T)1024);
2406 } else if (strwicmp(end, "T") == 0) {
2407 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2408 (SMB_OFF_T)1024 * (SMB_OFF_T)1024);
2409 } else if (strwicmp(end, "P") == 0) {
2410 lval *= ((SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2411 (SMB_OFF_T)1024 * (SMB_OFF_T)1024 *
2412 (SMB_OFF_T)1024);
2413 } else {
2414 return 0;
2415 }
2416
2417 /* Primitive attempt to detect wrapping on platforms with
2418 * 4-byte SMB_OFF_T. It's better to let the caller handle
2419 * a failure than some random number.
2420 */
2421 if (lval_orig <= lval) {
2422 return 0;
2423 }
2424 }
2425
2426 return lval;
2427}
2428
2429void string_append(char **left, const char *right)
2430{
2431 int new_len = strlen(right) + 1;
2432
2433 if (*left == NULL) {
2434 *left = (char *)SMB_MALLOC(new_len);
2435 *left[0] = '\0';
2436 } else {
2437 new_len += strlen(*left);
2438 *left = (char *)SMB_REALLOC(*left, new_len);
2439 }
2440
2441 if (*left == NULL) {
2442 return;
2443 }
2444
2445 safe_strcat(*left, right, new_len-1);
2446}
2447
2448BOOL add_string_to_array(TALLOC_CTX *mem_ctx,
2449 const char *str, const char ***strings,
2450 int *num)
2451{
2452 char *dup_str = talloc_strdup(mem_ctx, str);
2453
2454 *strings = TALLOC_REALLOC_ARRAY(mem_ctx, *strings, const char *, (*num)+1);
2455
2456 if ((*strings == NULL) || (dup_str == NULL)) {
2457 *num = 0;
2458 return False;
2459 }
2460
2461 (*strings)[*num] = dup_str;
2462 *num += 1;
2463 return True;
2464}
2465
2466/* Append an sprintf'ed string. Double buffer size on demand. Usable without
2467 * error checking in between. The indiation that something weird happened is
2468 * string==NULL */
2469
2470void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
2471 size_t *bufsize, const char *fmt, ...)
2472{
2473 va_list ap;
2474 char *newstr;
2475 int ret;
2476 BOOL increased;
2477
2478 /* len<0 is an internal marker that something failed */
2479 if (*len < 0)
2480 goto error;
2481
2482 if (*string == NULL) {
2483 if (*bufsize == 0)
2484 *bufsize = 128;
2485
2486 *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
2487 if (*string == NULL)
2488 goto error;
2489 }
2490
2491 va_start(ap, fmt);
2492 ret = vasprintf(&newstr, fmt, ap);
2493 va_end(ap);
2494
2495 if (ret < 0)
2496 goto error;
2497
2498 increased = False;
2499
2500 while ((*len)+ret >= *bufsize) {
2501 increased = True;
2502 *bufsize *= 2;
2503 if (*bufsize >= (1024*1024*256))
2504 goto error;
2505 }
2506
2507 if (increased) {
2508 *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
2509 *bufsize);
2510 if (*string == NULL) {
2511 goto error;
2512 }
2513 }
2514
2515 StrnCpy((*string)+(*len), newstr, ret);
2516 (*len) += ret;
2517 free(newstr);
2518 return;
2519
2520 error:
2521 *len = -1;
2522 *string = NULL;
2523}
2524
2525/*
2526 Returns the substring from src between the first occurrence of
2527 the char "front" and the first occurence of the char "back".
2528 Mallocs the return string which must be freed. Not for use
2529 with wide character strings.
2530*/
2531char *sstring_sub(const char *src, char front, char back)
2532{
2533 char *temp1, *temp2, *temp3;
2534 ptrdiff_t len;
2535
2536 temp1 = strchr(src, front);
2537 if (temp1 == NULL) return NULL;
2538 temp2 = strchr(src, back);
2539 if (temp2 == NULL) return NULL;
2540 len = temp2 - temp1;
2541 if (len <= 0) return NULL;
2542 temp3 = (char*)SMB_MALLOC(len);
2543 if (temp3 == NULL) {
2544 DEBUG(1,("Malloc failure in sstring_sub\n"));
2545 return NULL;
2546 }
2547 memcpy(temp3, temp1+1, len-1);
2548 temp3[len-1] = '\0';
2549 return temp3;
2550}
2551
2552/********************************************************************
2553 Check a string for any occurrences of a specified list of invalid
2554 characters.
2555********************************************************************/
2556
2557BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len )
2558{
2559 int i;
2560
2561 for ( i=0; i<max_len && name[i]; i++ ) {
2562 /* fail if strchr_m() finds one of the invalid characters */
2563 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
2564 return False;
2565 }
2566 }
2567
2568 return True;
2569}
2570
2571
2572/**
2573return the number of bytes occupied by a buffer in ASCII format
2574the result includes the null termination
2575limited by 'n' bytes
2576**/
2577size_t ascii_len_n(const char *src, size_t n)
2578{
2579 size_t len;
2580
2581 len = strnlen(src, n);
2582 if (len+1 <= n) {
2583 len += 1;
2584 }
2585
2586 return len;
2587}
2588
2589/**
2590return the number of bytes occupied by a buffer in CH_UTF16 format
2591the result includes the null termination
2592**/
2593size_t utf16_len(const void *buf)
2594{
2595 size_t len;
2596
2597 for (len = 0; SVAL(buf,len); len += 2) ;
2598
2599 return len + 2;
2600}
2601
2602/**
2603return the number of bytes occupied by a buffer in CH_UTF16 format
2604the result includes the null termination
2605limited by 'n' bytes
2606**/
2607size_t utf16_len_n(const void *src, size_t n)
2608{
2609 size_t len;
2610
2611 for (len = 0; (len+2 < n) && SVAL(src, len); len += 2) ;
2612
2613 if (len+2 <= n) {
2614 len += 2;
2615 }
2616
2617 return len;
2618}
2619
2620/*******************************************************************
2621 Add a shell escape character '\' to any character not in a known list
2622 of characters. UNIX charset format.
2623*******************************************************************/
2624
2625#define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,:"
2626#define INSIDE_DQUOTE_LIST "$`\n\"\\"
2627
2628char *escape_shell_string(const char *src)
2629{
2630 size_t srclen = strlen(src);
2631 char *ret = SMB_MALLOC((srclen * 2) + 1);
2632 char *dest = ret;
2633 BOOL in_s_quote = False;
2634 BOOL in_d_quote = False;
2635 BOOL next_escaped = False;
2636
2637 if (!ret) {
2638 return NULL;
2639 }
2640
2641 while (*src) {
2642 size_t c_size;
2643 codepoint_t c = next_codepoint(src, &c_size);
2644
2645 if (c == INVALID_CODEPOINT) {
2646 SAFE_FREE(ret);
2647 return NULL;
2648 }
2649
2650 if (c_size > 1) {
2651 memcpy(dest, src, c_size);
2652 src += c_size;
2653 dest += c_size;
2654 next_escaped = False;
2655 continue;
2656 }
2657
2658 /*
2659 * Deal with backslash escaped state.
2660 * This only lasts for one character.
2661 */
2662
2663 if (next_escaped) {
2664 *dest++ = *src++;
2665 next_escaped = False;
2666 continue;
2667 }
2668
2669 /*
2670 * Deal with single quote state. The
2671 * only thing we care about is exiting
2672 * this state.
2673 */
2674
2675 if (in_s_quote) {
2676 if (*src == '\'') {
2677 in_s_quote = False;
2678 }
2679 *dest++ = *src++;
2680 continue;
2681 }
2682
2683 /*
2684 * Deal with double quote state. The most
2685 * complex state. We must cope with \, meaning
2686 * possibly escape next char (depending what it
2687 * is), ", meaning exit this state, and possibly
2688 * add an \ escape to any unprotected character
2689 * (listed in INSIDE_DQUOTE_LIST).
2690 */
2691
2692 if (in_d_quote) {
2693 if (*src == '\\') {
2694 /*
2695 * Next character might be escaped.
2696 * We have to peek. Inside double
2697 * quotes only INSIDE_DQUOTE_LIST
2698 * characters are escaped by a \.
2699 */
2700
2701 char nextchar;
2702
2703 c = next_codepoint(&src[1], &c_size);
2704 if (c == INVALID_CODEPOINT) {
2705 SAFE_FREE(ret);
2706 return NULL;
2707 }
2708 if (c_size > 1) {
2709 /*
2710 * Don't escape the next char.
2711 * Just copy the \.
2712 */
2713 *dest++ = *src++;
2714 continue;
2715 }
2716
2717 nextchar = src[1];
2718
2719 if (nextchar && strchr(INSIDE_DQUOTE_LIST, (int)nextchar)) {
2720 next_escaped = True;
2721 }
2722 *dest++ = *src++;
2723 continue;
2724 }
2725
2726 if (*src == '\"') {
2727 /* Exit double quote state. */
2728 in_d_quote = False;
2729 *dest++ = *src++;
2730 continue;
2731 }
2732
2733 /*
2734 * We know the character isn't \ or ",
2735 * so escape it if it's any of the other
2736 * possible unprotected characters.
2737 */
2738
2739 if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
2740 *dest++ = '\\';
2741 }
2742 *dest++ = *src++;
2743 continue;
2744 }
2745
2746 /*
2747 * From here to the end of the loop we're
2748 * not in the single or double quote state.
2749 */
2750
2751 if (*src == '\\') {
2752 /* Next character must be escaped. */
2753 next_escaped = True;
2754 *dest++ = *src++;
2755 continue;
2756 }
2757
2758 if (*src == '\'') {
2759 /* Go into single quote state. */
2760 in_s_quote = True;
2761 *dest++ = *src++;
2762 continue;
2763 }
2764
2765 if (*src == '\"') {
2766 /* Go into double quote state. */
2767 in_d_quote = True;
2768 *dest++ = *src++;
2769 continue;
2770 }
2771
2772 /* Check if we need to escape the character. */
2773
2774 if (!strchr(INCLUDE_LIST, (int)*src)) {
2775 *dest++ = '\\';
2776 }
2777 *dest++ = *src++;
2778 }
2779 *dest++ = '\0';
2780 return ret;
2781}
Note: See TracBrowser for help on using the repository browser.