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