~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to lib/util/charset/util_unistr.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
   Copyright (C) Andrew Tridgell 1992-2001
 
5
   Copyright (C) Simo Sorce 2001
 
6
   
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 3 of the License, or
 
10
   (at your option) any later version.
 
11
   
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
   
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
*/
 
20
 
 
21
#include "includes.h"
 
22
#include "system/locale.h"
 
23
 
 
24
struct smb_iconv_convenience *global_iconv_convenience = NULL;
 
25
 
 
26
static inline struct smb_iconv_convenience *get_iconv_convenience(void)
 
27
{
 
28
        if (global_iconv_convenience == NULL)
 
29
                global_iconv_convenience = smb_iconv_convenience_init(talloc_autofree_context(), "ASCII", "UTF-8", true);
 
30
        return global_iconv_convenience;
 
31
}
 
32
 
 
33
/**
 
34
 Case insensitive string compararison
 
35
**/
 
36
_PUBLIC_ int strcasecmp_m(const char *s1, const char *s2)
 
37
{
 
38
        codepoint_t c1=0, c2=0;
 
39
        size_t size1, size2;
 
40
        struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
 
41
 
 
42
        /* handle null ptr comparisons to simplify the use in qsort */
 
43
        if (s1 == s2) return 0;
 
44
        if (s1 == NULL) return -1;
 
45
        if (s2 == NULL) return 1;
 
46
 
 
47
        while (*s1 && *s2) {
 
48
                c1 = next_codepoint_convenience(iconv_convenience, s1, &size1);
 
49
                c2 = next_codepoint_convenience(iconv_convenience, s2, &size2);
 
50
 
 
51
                s1 += size1;
 
52
                s2 += size2;
 
53
 
 
54
                if (c1 == c2) {
 
55
                        continue;
 
56
                }
 
57
 
 
58
                if (c1 == INVALID_CODEPOINT ||
 
59
                    c2 == INVALID_CODEPOINT) {
 
60
                        /* what else can we do?? */
 
61
                        return strcasecmp(s1, s2);
 
62
                }
 
63
 
 
64
                if (toupper_m(c1) != toupper_m(c2)) {
 
65
                        return c1 - c2;
 
66
                }
 
67
        }
 
68
 
 
69
        return *s1 - *s2;
 
70
}
 
71
 
 
72
/**
 
73
 * Get the next token from a string, return False if none found.
 
74
 * Handles double-quotes.
 
75
 * 
 
76
 * Based on a routine by GJC@VILLAGE.COM. 
 
77
 * Extensively modified by Andrew.Tridgell@anu.edu.au
 
78
 **/
 
79
_PUBLIC_ bool next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
 
80
{
 
81
        const char *s;
 
82
        bool quoted;
 
83
        size_t len=1;
 
84
 
 
85
        if (!ptr)
 
86
                return false;
 
87
 
 
88
        s = *ptr;
 
89
 
 
90
        /* default to simple separators */
 
91
        if (!sep)
 
92
                sep = " \t\n\r";
 
93
 
 
94
        /* find the first non sep char */
 
95
        while (*s && strchr_m(sep,*s))
 
96
                s++;
 
97
        
 
98
        /* nothing left? */
 
99
        if (!*s)
 
100
                return false;
 
101
        
 
102
        /* copy over the token */
 
103
        for (quoted = false; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
 
104
                if (*s == '\"') {
 
105
                        quoted = !quoted;
 
106
                } else {
 
107
                        len++;
 
108
                        *buff++ = *s;
 
109
                }
 
110
        }
 
111
        
 
112
        *ptr = (*s) ? s+1 : s;  
 
113
        *buff = 0;
 
114
        
 
115
        return true;
 
116
}
 
117
 
 
118
/**
 
119
 Case insensitive string compararison, length limited
 
120
**/
 
121
_PUBLIC_ int strncasecmp_m(const char *s1, const char *s2, size_t n)
 
122
{
 
123
        codepoint_t c1=0, c2=0;
 
124
        size_t size1, size2;
 
125
        struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
 
126
 
 
127
        /* handle null ptr comparisons to simplify the use in qsort */
 
128
        if (s1 == s2) return 0;
 
129
        if (s1 == NULL) return -1;
 
130
        if (s2 == NULL) return 1;
 
131
 
 
132
        while (*s1 && *s2 && n) {
 
133
                n--;
 
134
 
 
135
                c1 = next_codepoint_convenience(iconv_convenience, s1, &size1);
 
136
                c2 = next_codepoint_convenience(iconv_convenience, s2, &size2);
 
137
 
 
138
                s1 += size1;
 
139
                s2 += size2;
 
140
 
 
141
                if (c1 == c2) {
 
142
                        continue;
 
143
                }
 
144
 
 
145
                if (c1 == INVALID_CODEPOINT ||
 
146
                    c2 == INVALID_CODEPOINT) {
 
147
                        /* what else can we do?? */
 
148
                        return strcasecmp(s1, s2);
 
149
                }
 
150
 
 
151
                if (toupper_m(c1) != toupper_m(c2)) {
 
152
                        return c1 - c2;
 
153
                }
 
154
        }
 
155
 
 
156
        if (n == 0) {
 
157
                return 0;
 
158
        }
 
159
 
 
160
        return *s1 - *s2;
 
161
}
 
162
 
 
163
/**
 
164
 * Compare 2 strings.
 
165
 *
 
166
 * @note The comparison is case-insensitive.
 
167
 **/
 
168
_PUBLIC_ bool strequal_m(const char *s1, const char *s2)
 
169
{
 
170
        return strcasecmp_m(s1,s2) == 0;
 
171
}
 
172
 
 
173
/**
 
174
 Compare 2 strings (case sensitive).
 
175
**/
 
176
_PUBLIC_ bool strcsequal_m(const char *s1,const char *s2)
 
177
{
 
178
        if (s1 == s2)
 
179
                return true;
 
180
        if (!s1 || !s2)
 
181
                return false;
 
182
        
 
183
        return strcmp(s1,s2) == 0;
 
184
}
 
185
 
 
186
 
 
187
/**
 
188
 String replace.
 
189
 NOTE: oldc and newc must be 7 bit characters
 
190
**/
 
191
_PUBLIC_ void string_replace_m(char *s, char oldc, char newc)
 
192
{
 
193
        struct smb_iconv_convenience *ic = get_iconv_convenience();
 
194
        while (s && *s) {
 
195
                size_t size;
 
196
                codepoint_t c = next_codepoint_convenience(ic, s, &size);
 
197
                if (c == oldc) {
 
198
                        *s = newc;
 
199
                }
 
200
                s += size;
 
201
        }
 
202
}
 
203
 
 
204
/**
 
205
 Paranoid strcpy into a buffer of given length (includes terminating
 
206
 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
 
207
 and replaces with '_'. Deliberately does *NOT* check for multibyte
 
208
 characters. Don't change it !
 
209
**/
 
210
 
 
211
_PUBLIC_ char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
 
212
{
 
213
        size_t len, i;
 
214
 
 
215
        if (maxlength == 0) {
 
216
                /* can't fit any bytes at all! */
 
217
                return NULL;
 
218
        }
 
219
 
 
220
        if (!dest) {
 
221
                DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
 
222
                return NULL;
 
223
        }
 
224
 
 
225
        if (!src) {
 
226
                *dest = 0;
 
227
                return dest;
 
228
        }  
 
229
 
 
230
        len = strlen(src);
 
231
        if (len >= maxlength)
 
232
                len = maxlength - 1;
 
233
 
 
234
        if (!other_safe_chars)
 
235
                other_safe_chars = "";
 
236
 
 
237
        for(i = 0; i < len; i++) {
 
238
                int val = (src[i] & 0xff);
 
239
                if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
 
240
                        dest[i] = src[i];
 
241
                else
 
242
                        dest[i] = '_';
 
243
        }
 
244
 
 
245
        dest[i] = '\0';
 
246
 
 
247
        return dest;
 
248
}
 
249
 
 
250
/**
 
251
 Count the number of UCS2 characters in a string. Normally this will
 
252
 be the same as the number of bytes in a string for single byte strings,
 
253
 but will be different for multibyte.
 
254
**/
 
255
_PUBLIC_ size_t strlen_m(const char *s)
 
256
{
 
257
        size_t count = 0;
 
258
        struct smb_iconv_convenience *ic = get_iconv_convenience();
 
259
 
 
260
        if (!s) {
 
261
                return 0;
 
262
        }
 
263
 
 
264
        while (*s && !(((uint8_t)*s) & 0x80)) {
 
265
                s++;
 
266
                count++;
 
267
        }
 
268
 
 
269
        if (!*s) {
 
270
                return count;
 
271
        }
 
272
 
 
273
        while (*s) {
 
274
                size_t c_size;
 
275
                codepoint_t c = next_codepoint_convenience(ic, s, &c_size);
 
276
                if (c < 0x10000) {
 
277
                        count += 1;
 
278
                } else {
 
279
                        count += 2;
 
280
                }
 
281
                s += c_size;
 
282
        }
 
283
 
 
284
        return count;
 
285
}
 
286
 
 
287
/**
 
288
   Work out the number of multibyte chars in a string, including the NULL
 
289
   terminator.
 
290
**/
 
291
_PUBLIC_ size_t strlen_m_term(const char *s)
 
292
{
 
293
        if (!s) {
 
294
                return 0;
 
295
        }
 
296
 
 
297
        return strlen_m(s) + 1;
 
298
}
 
299
 
 
300
/*
 
301
 * Weird helper routine for the winreg pipe: If nothing is around, return 0,
 
302
 * if a string is there, include the terminator.
 
303
 */
 
304
 
 
305
_PUBLIC_ size_t strlen_m_term_null(const char *s)
 
306
{
 
307
        size_t len;
 
308
        if (!s) {
 
309
                return 0;
 
310
        }
 
311
        len = strlen_m(s);
 
312
        if (len == 0) {
 
313
                return 0;
 
314
        }
 
315
 
 
316
        return len+1;
 
317
}
 
318
 
 
319
/**
 
320
 Strchr and strrchr_m are a bit complex on general multi-byte strings. 
 
321
**/
 
322
_PUBLIC_ char *strchr_m(const char *s, char c)
 
323
{
 
324
        struct smb_iconv_convenience *ic = get_iconv_convenience();
 
325
        if (s == NULL) {
 
326
                return NULL;
 
327
        }
 
328
        /* characters below 0x3F are guaranteed to not appear in
 
329
           non-initial position in multi-byte charsets */
 
330
        if ((c & 0xC0) == 0) {
 
331
                return strchr(s, c);
 
332
        }
 
333
 
 
334
        while (*s) {
 
335
                size_t size;
 
336
                codepoint_t c2 = next_codepoint_convenience(ic, s, &size);
 
337
                if (c2 == c) {
 
338
                        return discard_const_p(char, s);
 
339
                }
 
340
                s += size;
 
341
        }
 
342
 
 
343
        return NULL;
 
344
}
 
345
 
 
346
/**
 
347
 * Multibyte-character version of strrchr
 
348
 */
 
349
_PUBLIC_ char *strrchr_m(const char *s, char c)
 
350
{
 
351
        struct smb_iconv_convenience *ic = get_iconv_convenience();
 
352
        char *ret = NULL;
 
353
 
 
354
        if (s == NULL) {
 
355
                return NULL;
 
356
        }
 
357
 
 
358
        /* characters below 0x3F are guaranteed to not appear in
 
359
           non-initial position in multi-byte charsets */
 
360
        if ((c & 0xC0) == 0) {
 
361
                return strrchr(s, c);
 
362
        }
 
363
 
 
364
        while (*s) {
 
365
                size_t size;
 
366
                codepoint_t c2 = next_codepoint_convenience(ic, s, &size);
 
367
                if (c2 == c) {
 
368
                        ret = discard_const_p(char, s);
 
369
                }
 
370
                s += size;
 
371
        }
 
372
 
 
373
        return ret;
 
374
}
 
375
 
 
376
/**
 
377
  return True if any (multi-byte) character is lower case
 
378
*/
 
379
_PUBLIC_ bool strhaslower(const char *string)
 
380
{
 
381
        struct smb_iconv_convenience *ic = get_iconv_convenience();
 
382
        while (*string) {
 
383
                size_t c_size;
 
384
                codepoint_t s;
 
385
                codepoint_t t;
 
386
 
 
387
                s = next_codepoint_convenience(ic, string, &c_size);
 
388
                string += c_size;
 
389
 
 
390
                t = toupper_m(s);
 
391
 
 
392
                if (s != t) {
 
393
                        return true; /* that means it has lower case chars */
 
394
                }
 
395
        }
 
396
 
 
397
        return false;
 
398
 
399
 
 
400
/**
 
401
  return True if any (multi-byte) character is upper case
 
402
*/
 
403
_PUBLIC_ bool strhasupper(const char *string)
 
404
{
 
405
        struct smb_iconv_convenience *ic = get_iconv_convenience();
 
406
        while (*string) {
 
407
                size_t c_size;
 
408
                codepoint_t s;
 
409
                codepoint_t t;
 
410
 
 
411
                s = next_codepoint_convenience(ic, string, &c_size);
 
412
                string += c_size;
 
413
 
 
414
                t = tolower_m(s);
 
415
 
 
416
                if (s != t) {
 
417
                        return true; /* that means it has upper case chars */
 
418
                }
 
419
        }
 
420
 
 
421
        return false;
 
422
 
423
 
 
424
/**
 
425
 Convert a string to lower case, allocated with talloc
 
426
**/
 
427
_PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
 
428
{
 
429
        size_t size=0;
 
430
        char *dest;
 
431
        struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
 
432
 
 
433
        /* this takes advantage of the fact that upper/lower can't
 
434
           change the length of a character by more than 1 byte */
 
435
        dest = talloc_array(ctx, char, 2*(strlen(src))+1);
 
436
        if (dest == NULL) {
 
437
                return NULL;
 
438
        }
 
439
 
 
440
        while (*src) {
 
441
                size_t c_size;
 
442
                codepoint_t c = next_codepoint_convenience(iconv_convenience, src, &c_size);
 
443
                src += c_size;
 
444
 
 
445
                c = tolower_m(c);
 
446
 
 
447
                c_size = push_codepoint(iconv_convenience, dest+size, c);
 
448
                if (c_size == -1) {
 
449
                        talloc_free(dest);
 
450
                        return NULL;
 
451
                }
 
452
                size += c_size;
 
453
        }
 
454
 
 
455
        dest[size] = 0;
 
456
 
 
457
        /* trim it so talloc_append_string() works */
 
458
        dest = talloc_realloc(ctx, dest, char, size+1);
 
459
 
 
460
        talloc_set_name_const(dest, dest);
 
461
 
 
462
        return dest;
 
463
}
 
464
 
 
465
/**
 
466
 Convert a string to UPPER case, allocated with talloc
 
467
 source length limited to n bytes
 
468
**/
 
469
_PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n)
 
470
{
 
471
        size_t size=0;
 
472
        char *dest;
 
473
        struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
 
474
        
 
475
        if (!src) {
 
476
                return NULL;
 
477
        }
 
478
 
 
479
        /* this takes advantage of the fact that upper/lower can't
 
480
           change the length of a character by more than 1 byte */
 
481
        dest = talloc_array(ctx, char, 2*(n+1));
 
482
        if (dest == NULL) {
 
483
                return NULL;
 
484
        }
 
485
 
 
486
        while (*src && n--) {
 
487
                size_t c_size;
 
488
                codepoint_t c = next_codepoint_convenience(iconv_convenience, src, &c_size);
 
489
                src += c_size;
 
490
 
 
491
                c = toupper_m(c);
 
492
 
 
493
                c_size = push_codepoint(iconv_convenience, dest+size, c);
 
494
                if (c_size == -1) {
 
495
                        talloc_free(dest);
 
496
                        return NULL;
 
497
                }
 
498
                size += c_size;
 
499
        }
 
500
 
 
501
        dest[size] = 0;
 
502
 
 
503
        /* trim it so talloc_append_string() works */
 
504
        dest = talloc_realloc(ctx, dest, char, size+1);
 
505
 
 
506
        talloc_set_name_const(dest, dest);
 
507
 
 
508
        return dest;
 
509
}
 
510
 
 
511
/**
 
512
 Convert a string to UPPER case, allocated with talloc
 
513
**/
 
514
_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
 
515
{
 
516
        return strupper_talloc_n(ctx, src, src?strlen(src):0);
 
517
}
 
518
 
 
519
/**
 
520
 talloc_strdup() a unix string to upper case.
 
521
**/
 
522
_PUBLIC_ char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *src)
 
523
{
 
524
        return strupper_talloc(ctx, src);
 
525
}
 
526
 
 
527
/**
 
528
 Convert a string to lower case.
 
529
**/
 
530
_PUBLIC_ void strlower_m(char *s)
 
531
{
 
532
        char *d;
 
533
        struct smb_iconv_convenience *iconv_convenience;
 
534
 
 
535
        /* this is quite a common operation, so we want it to be
 
536
           fast. We optimise for the ascii case, knowing that all our
 
537
           supported multi-byte character sets are ascii-compatible
 
538
           (ie. they match for the first 128 chars) */
 
539
        while (*s && !(((uint8_t)*s) & 0x80)) {
 
540
                *s = tolower((uint8_t)*s);
 
541
                s++;
 
542
        }
 
543
 
 
544
        if (!*s)
 
545
                return;
 
546
 
 
547
        iconv_convenience = get_iconv_convenience();
 
548
 
 
549
        d = s;
 
550
 
 
551
        while (*s) {
 
552
                size_t c_size, c_size2;
 
553
                codepoint_t c = next_codepoint_convenience(iconv_convenience, s, &c_size);
 
554
                c_size2 = push_codepoint(iconv_convenience, d, tolower_m(c));
 
555
                if (c_size2 > c_size) {
 
556
                        DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
 
557
                                 c, tolower_m(c), (int)c_size, (int)c_size2));
 
558
                        smb_panic("codepoint expansion in strlower_m\n");
 
559
                }
 
560
                s += c_size;
 
561
                d += c_size2;
 
562
        }
 
563
        *d = 0;
 
564
}
 
565
 
 
566
/**
 
567
 Convert a string to UPPER case.
 
568
**/
 
569
_PUBLIC_ void strupper_m(char *s)
 
570
{
 
571
        char *d;
 
572
        struct smb_iconv_convenience *iconv_convenience;
 
573
 
 
574
        /* this is quite a common operation, so we want it to be
 
575
           fast. We optimise for the ascii case, knowing that all our
 
576
           supported multi-byte character sets are ascii-compatible
 
577
           (ie. they match for the first 128 chars) */
 
578
        while (*s && !(((uint8_t)*s) & 0x80)) {
 
579
                *s = toupper((uint8_t)*s);
 
580
                s++;
 
581
        }
 
582
 
 
583
        if (!*s)
 
584
                return;
 
585
 
 
586
        iconv_convenience = get_iconv_convenience();
 
587
 
 
588
        d = s;
 
589
 
 
590
        while (*s) {
 
591
                size_t c_size, c_size2;
 
592
                codepoint_t c = next_codepoint_convenience(iconv_convenience, s, &c_size);
 
593
                c_size2 = push_codepoint(iconv_convenience, d, toupper_m(c));
 
594
                if (c_size2 > c_size) {
 
595
                        DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
 
596
                                 c, toupper_m(c), (int)c_size, (int)c_size2));
 
597
                        smb_panic("codepoint expansion in strupper_m\n");
 
598
                }
 
599
                s += c_size;
 
600
                d += c_size2;
 
601
        }
 
602
        *d = 0;
 
603
}
 
604
 
 
605
 
 
606
/**
 
607
 Find the number of 'c' chars in a string
 
608
**/
 
609
_PUBLIC_ size_t count_chars_m(const char *s, char c)
 
610
{
 
611
        struct smb_iconv_convenience *ic = get_iconv_convenience();
 
612
        size_t count = 0;
 
613
 
 
614
        while (*s) {
 
615
                size_t size;
 
616
                codepoint_t c2 = next_codepoint_convenience(ic, s, &size);
 
617
                if (c2 == c) count++;
 
618
                s += size;
 
619
        }
 
620
 
 
621
        return count;
 
622
}
 
623
 
 
624
 
 
625
/**
 
626
 * Copy a string from a char* unix src to a dos codepage string destination.
 
627
 *
 
628
 * @return the number of bytes occupied by the string in the destination.
 
629
 *
 
630
 * @param flags can include
 
631
 * <dl>
 
632
 * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
 
633
 * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
 
634
 * </dl>
 
635
 *
 
636
 * @param dest_len the maximum length in bytes allowed in the
 
637
 * destination.  If @p dest_len is -1 then no maximum is used.
 
638
 **/
 
639
static ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
 
640
{
 
641
        size_t src_len;
 
642
        ssize_t ret;
 
643
 
 
644
        if (flags & STR_UPPER) {
 
645
                char *tmpbuf = strupper_talloc(NULL, src);
 
646
                if (tmpbuf == NULL) {
 
647
                        return -1;
 
648
                }
 
649
                ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
 
650
                talloc_free(tmpbuf);
 
651
                return ret;
 
652
        }
 
653
 
 
654
        src_len = strlen(src);
 
655
 
 
656
        if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
 
657
                src_len++;
 
658
 
 
659
        return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, false);
 
660
}
 
661
 
 
662
/**
 
663
 * Copy a string from a unix char* src to an ASCII destination,
 
664
 * allocating a buffer using talloc().
 
665
 *
 
666
 * @param dest always set at least to NULL 
 
667
 *
 
668
 * @returns The number of bytes occupied by the string in the destination
 
669
 *         or -1 in case of error.
 
670
 **/
 
671
_PUBLIC_ bool push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
 
672
{
 
673
        size_t src_len = strlen(src)+1;
 
674
        *dest = NULL;
 
675
        return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest, converted_size, false);
 
676
}
 
677
 
 
678
 
 
679
/**
 
680
 * Copy a string from a dos codepage source to a unix char* destination.
 
681
 *
 
682
 * The resulting string in "dest" is always null terminated.
 
683
 *
 
684
 * @param flags can have:
 
685
 * <dl>
 
686
 * <dt>STR_TERMINATE</dt>
 
687
 * <dd>STR_TERMINATE means the string in @p src
 
688
 * is null terminated, and src_len is ignored.</dd>
 
689
 * </dl>
 
690
 *
 
691
 * @param src_len is the length of the source area in bytes.
 
692
 * @returns the number of bytes occupied by the string in @p src.
 
693
 **/
 
694
static ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
 
695
{
 
696
        size_t ret;
 
697
 
 
698
        if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
 
699
                if (src_len == (size_t)-1) {
 
700
                        src_len = strlen((const char *)src) + 1;
 
701
                } else {
 
702
                        size_t len = strnlen((const char *)src, src_len);
 
703
                        if (len < src_len)
 
704
                                len++;
 
705
                        src_len = len;
 
706
                }
 
707
        }
 
708
 
 
709
        ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, false);
 
710
 
 
711
        if (dest_len)
 
712
                dest[MIN(ret, dest_len-1)] = 0;
 
713
 
 
714
        return src_len;
 
715
}
 
716
 
 
717
/**
 
718
 * Copy a string from a char* src to a unicode destination.
 
719
 *
 
720
 * @returns the number of bytes occupied by the string in the destination.
 
721
 *
 
722
 * @param flags can have:
 
723
 *
 
724
 * <dl>
 
725
 * <dt>STR_TERMINATE <dd>means include the null termination.
 
726
 * <dt>STR_UPPER     <dd>means uppercase in the destination.
 
727
 * <dt>STR_NOALIGN   <dd>means don't do alignment.
 
728
 * </dl>
 
729
 *
 
730
 * @param dest_len is the maximum length allowed in the
 
731
 * destination. If dest_len is -1 then no maxiumum is used.
 
732
 **/
 
733
static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags)
 
734
{
 
735
        size_t len=0;
 
736
        size_t src_len = strlen(src);
 
737
        size_t ret;
 
738
 
 
739
        if (flags & STR_UPPER) {
 
740
                char *tmpbuf = strupper_talloc(NULL, src);
 
741
                if (tmpbuf == NULL) {
 
742
                        return -1;
 
743
                }
 
744
                ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
 
745
                talloc_free(tmpbuf);
 
746
                return ret;
 
747
        }
 
748
 
 
749
        if (flags & STR_TERMINATE)
 
750
                src_len++;
 
751
 
 
752
        if (ucs2_align(NULL, dest, flags)) {
 
753
                *(char *)dest = 0;
 
754
                dest = (void *)((char *)dest + 1);
 
755
                if (dest_len) dest_len--;
 
756
                len++;
 
757
        }
 
758
 
 
759
        /* ucs2 is always a multiple of 2 bytes */
 
760
        dest_len &= ~1;
 
761
 
 
762
        ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len, false);
 
763
        if (ret == (size_t)-1) {
 
764
                return 0;
 
765
        }
 
766
 
 
767
        len += ret;
 
768
 
 
769
        return len;
 
770
}
 
771
 
 
772
 
 
773
/**
 
774
 * Copy a string from a unix char* src to a UCS2 destination,
 
775
 * allocating a buffer using talloc().
 
776
 *
 
777
 * @param dest always set at least to NULL 
 
778
 *
 
779
 * @returns The number of bytes occupied by the string in the destination
 
780
 *         or -1 in case of error.
 
781
 **/
 
782
_PUBLIC_ bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src, size_t *converted_size)
 
783
{
 
784
        size_t src_len = strlen(src)+1;
 
785
        *dest = NULL;
 
786
        return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, (void **)dest, converted_size, false);
 
787
}
 
788
 
 
789
 
 
790
/**
 
791
 * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
 
792
 *
 
793
 * @param dest always set at least to NULL 
 
794
 *
 
795
 * @returns The number of bytes occupied by the string in the destination
 
796
 **/
 
797
 
 
798
_PUBLIC_ bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
 
799
{
 
800
        size_t src_len = strlen(src)+1;
 
801
        *dest = NULL;
 
802
        return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, converted_size, false);
 
803
}
 
804
 
 
805
/**
 
806
 Copy a string from a ucs2 source to a unix char* destination.
 
807
 Flags can have:
 
808
  STR_TERMINATE means the string in src is null terminated.
 
809
  STR_NOALIGN   means don't try to align.
 
810
 if STR_TERMINATE is set then src_len is ignored if it is -1.
 
811
 src_len is the length of the source area in bytes
 
812
 Return the number of bytes occupied by the string in src.
 
813
 The resulting string in "dest" is always null terminated.
 
814
**/
 
815
 
 
816
static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
 
817
{
 
818
        size_t ret;
 
819
 
 
820
        if (ucs2_align(NULL, src, flags)) {
 
821
                src = (const void *)((const char *)src + 1);
 
822
                if (src_len > 0)
 
823
                        src_len--;
 
824
        }
 
825
 
 
826
        if (flags & STR_TERMINATE) {
 
827
                if (src_len == (size_t)-1) {
 
828
                        src_len = utf16_len(src);
 
829
                } else {
 
830
                        src_len = utf16_len_n(src, src_len);
 
831
                }
 
832
        }
 
833
 
 
834
        /* ucs2 is always a multiple of 2 bytes */
 
835
        if (src_len != (size_t)-1)
 
836
                src_len &= ~1;
 
837
        
 
838
        ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len, false);
 
839
        if (dest_len)
 
840
                dest[MIN(ret, dest_len-1)] = 0;
 
841
 
 
842
        return src_len;
 
843
}
 
844
 
 
845
/**
 
846
 * Copy a string from a ASCII src to a unix char * destination, allocating a buffer using talloc
 
847
 *
 
848
 * @param dest always set at least to NULL 
 
849
 *
 
850
 * @returns The number of bytes occupied by the string in the destination
 
851
 **/
 
852
 
 
853
_PUBLIC_ bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
 
854
{
 
855
        size_t src_len = strlen(src)+1;
 
856
        *dest = NULL;
 
857
        return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, converted_size, false);
 
858
}
 
859
 
 
860
/**
 
861
 * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
 
862
 *
 
863
 * @param dest always set at least to NULL 
 
864
 *
 
865
 * @returns The number of bytes occupied by the string in the destination
 
866
 **/
 
867
 
 
868
_PUBLIC_ bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src, size_t *converted_size)
 
869
{
 
870
        size_t src_len = utf16_len(src);
 
871
        *dest = NULL;
 
872
        return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest, converted_size, false);
 
873
}
 
874
 
 
875
/**
 
876
 * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
 
877
 *
 
878
 * @param dest always set at least to NULL 
 
879
 *
 
880
 * @returns The number of bytes occupied by the string in the destination
 
881
 **/
 
882
 
 
883
_PUBLIC_ bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src, size_t *converted_size)
 
884
{
 
885
        size_t src_len = strlen(src)+1;
 
886
        *dest = NULL;
 
887
        return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, converted_size, false);
 
888
}
 
889
 
 
890
/**
 
891
 Copy a string from a char* src to a unicode or ascii
 
892
 dos codepage destination choosing unicode or ascii based on the 
 
893
 flags in the SMB buffer starting at base_ptr.
 
894
 Return the number of bytes occupied by the string in the destination.
 
895
 flags can have:
 
896
  STR_TERMINATE means include the null termination.
 
897
  STR_UPPER     means uppercase in the destination.
 
898
  STR_ASCII     use ascii even with unicode packet.
 
899
  STR_NOALIGN   means don't do alignment.
 
900
 dest_len is the maximum length allowed in the destination. If dest_len
 
901
 is -1 then no maxiumum is used.
 
902
**/
 
903
 
 
904
_PUBLIC_ ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
 
905
{
 
906
        if (flags & STR_ASCII) {
 
907
                return push_ascii(dest, src, dest_len, flags);
 
908
        } else if (flags & STR_UNICODE) {
 
909
                return push_ucs2(dest, src, dest_len, flags);
 
910
        } else {
 
911
                smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set");
 
912
                return -1;
 
913
        }
 
914
}
 
915
 
 
916
 
 
917
/**
 
918
 Copy a string from a unicode or ascii source (depending on
 
919
 the packet flags) to a char* destination.
 
920
 Flags can have:
 
921
  STR_TERMINATE means the string in src is null terminated.
 
922
  STR_UNICODE   means to force as unicode.
 
923
  STR_ASCII     use ascii even with unicode packet.
 
924
  STR_NOALIGN   means don't do alignment.
 
925
 if STR_TERMINATE is set then src_len is ignored is it is -1
 
926
 src_len is the length of the source area in bytes.
 
927
 Return the number of bytes occupied by the string in src.
 
928
 The resulting string in "dest" is always null terminated.
 
929
**/
 
930
 
 
931
_PUBLIC_ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
 
932
{
 
933
        if (flags & STR_ASCII) {
 
934
                return pull_ascii(dest, src, dest_len, src_len, flags);
 
935
        } else if (flags & STR_UNICODE) {
 
936
                return pull_ucs2(dest, src, dest_len, src_len, flags);
 
937
        } else {
 
938
                smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set");
 
939
                return -1;
 
940
        }
 
941
}
 
942
 
 
943
 
 
944
/**
 
945
 * Convert string from one encoding to another, making error checking etc
 
946
 *
 
947
 * @param src pointer to source string (multibyte or singlebyte)
 
948
 * @param srclen length of the source string in bytes
 
949
 * @param dest pointer to destination string (multibyte or singlebyte)
 
950
 * @param destlen maximal length allowed for string
 
951
 * @returns the number of bytes occupied in the destination
 
952
 **/
 
953
_PUBLIC_ size_t convert_string(charset_t from, charset_t to,
 
954
                                void const *src, size_t srclen, 
 
955
                                void *dest, size_t destlen, 
 
956
                                bool allow_badcharcnv)
 
957
{
 
958
        size_t ret;
 
959
        if (!convert_string_convenience(get_iconv_convenience(), from, to, 
 
960
                                                                          src, srclen,
 
961
                                                                          dest, destlen, &ret,
 
962
                                                                          allow_badcharcnv))
 
963
                return -1;
 
964
        return ret;
 
965
}
 
966
 
 
967
/**
 
968
 * Convert between character sets, allocating a new buffer using talloc for the result.
 
969
 *
 
970
 * @param srclen length of source buffer.
 
971
 * @param dest always set at least to NULL
 
972
 * @param converted_size Size in bytes of the converted string
 
973
 * @note -1 is not accepted for srclen.
 
974
 *
 
975
 * @returns boolean indication whether the conversion succeeded
 
976
 **/
 
977
 
 
978
_PUBLIC_ bool convert_string_talloc(TALLOC_CTX *ctx, 
 
979
                                       charset_t from, charset_t to, 
 
980
                                       void const *src, size_t srclen, 
 
981
                                       void *dest, size_t *converted_size, 
 
982
                                           bool allow_badcharcnv)
 
983
{
 
984
        return convert_string_talloc_convenience(ctx, get_iconv_convenience(),
 
985
                                                                                         from, to, src, srclen, dest,
 
986
                                                                                         converted_size, 
 
987
                                                                                         allow_badcharcnv);
 
988
}
 
989
 
 
990
 
 
991
_PUBLIC_ codepoint_t next_codepoint(const char *str, size_t *size)
 
992
{
 
993
        return next_codepoint_convenience(get_iconv_convenience(), str, size);
 
994
}