~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/lib/util_str.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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