source: branches/samba-3.3.x/source/lib/util_str.c

Last change on this file was 206, checked in by Herwig Bauernfeind, 16 years ago

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

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