Merge branch 'master' of ssh://git.samba.org/data/git/samba into wspp-schema
[ira/wip.git] / lib / util / charset / util_unistr.c
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 }