Merge branch 'master' of ssh://git.samba.org/data/git/samba
[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 #include "param/param.h"
24
25 static inline struct smb_iconv_convenience *get_iconv_convenience(void)
26 {
27         static struct smb_iconv_convenience *ic = NULL;
28         if (ic == NULL)
29                 ic = lp_iconv_convenience(global_loadparm);
30         return ic;
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(iconv_convenience, s1, &size1);
49                 c2 = next_codepoint(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(iconv_convenience, s1, &size1);
136                 c2 = next_codepoint(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         while (s && *s) {
194                 size_t size;
195                 codepoint_t c = next_codepoint(get_iconv_convenience(), s, &size);
196                 if (c == oldc) {
197                         *s = newc;
198                 }
199                 s += size;
200         }
201 }
202
203 /**
204  Paranoid strcpy into a buffer of given length (includes terminating
205  zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
206  and replaces with '_'. Deliberately does *NOT* check for multibyte
207  characters. Don't change it !
208 **/
209
210 _PUBLIC_ char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
211 {
212         size_t len, i;
213
214         if (maxlength == 0) {
215                 /* can't fit any bytes at all! */
216                 return NULL;
217         }
218
219         if (!dest) {
220                 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
221                 return NULL;
222         }
223
224         if (!src) {
225                 *dest = 0;
226                 return dest;
227         }  
228
229         len = strlen(src);
230         if (len >= maxlength)
231                 len = maxlength - 1;
232
233         if (!other_safe_chars)
234                 other_safe_chars = "";
235
236         for(i = 0; i < len; i++) {
237                 int val = (src[i] & 0xff);
238                 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
239                         dest[i] = src[i];
240                 else
241                         dest[i] = '_';
242         }
243
244         dest[i] = '\0';
245
246         return dest;
247 }
248
249 /**
250  Count the number of UCS2 characters in a string. Normally this will
251  be the same as the number of bytes in a string for single byte strings,
252  but will be different for multibyte.
253 **/
254 _PUBLIC_ size_t strlen_m(const char *s)
255 {
256         size_t count = 0;
257
258         if (!s) {
259                 return 0;
260         }
261
262         while (*s && !(((uint8_t)*s) & 0x80)) {
263                 s++;
264                 count++;
265         }
266
267         if (!*s) {
268                 return count;
269         }
270
271         while (*s) {
272                 size_t c_size;
273                 codepoint_t c = next_codepoint(get_iconv_convenience(), s, &c_size);
274                 if (c < 0x10000) {
275                         count += 1;
276                 } else {
277                         count += 2;
278                 }
279                 s += c_size;
280         }
281
282         return count;
283 }
284
285 /**
286    Work out the number of multibyte chars in a string, including the NULL
287    terminator.
288 **/
289 _PUBLIC_ size_t strlen_m_term(const char *s)
290 {
291         if (!s) {
292                 return 0;
293         }
294
295         return strlen_m(s) + 1;
296 }
297
298 /**
299  Strchr and strrchr_m are a bit complex on general multi-byte strings. 
300 **/
301 _PUBLIC_ char *strchr_m(const char *s, char c)
302 {
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(get_iconv_convenience(), 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         char *ret = NULL;
330
331         if (s == NULL) {
332                 return NULL;
333         }
334
335         /* characters below 0x3F are guaranteed to not appear in
336            non-initial position in multi-byte charsets */
337         if ((c & 0xC0) == 0) {
338                 return strrchr(s, c);
339         }
340
341         while (*s) {
342                 size_t size;
343                 codepoint_t c2 = next_codepoint(get_iconv_convenience(), s, &size);
344                 if (c2 == c) {
345                         ret = discard_const_p(char, s);
346                 }
347                 s += size;
348         }
349
350         return ret;
351 }
352
353 /**
354   return True if any (multi-byte) character is lower case
355 */
356 _PUBLIC_ bool strhaslower(const char *string)
357 {
358         while (*string) {
359                 size_t c_size;
360                 codepoint_t s;
361                 codepoint_t t;
362
363                 s = next_codepoint(get_iconv_convenience(), string, &c_size);
364                 string += c_size;
365
366                 t = toupper_m(s);
367
368                 if (s != t) {
369                         return true; /* that means it has lower case chars */
370                 }
371         }
372
373         return false;
374
375
376 /**
377   return True if any (multi-byte) character is upper case
378 */
379 _PUBLIC_ bool strhasupper(const char *string)
380 {
381         while (*string) {
382                 size_t c_size;
383                 codepoint_t s;
384                 codepoint_t t;
385
386                 s = next_codepoint(get_iconv_convenience(), string, &c_size);
387                 string += c_size;
388
389                 t = tolower_m(s);
390
391                 if (s != t) {
392                         return true; /* that means it has upper case chars */
393                 }
394         }
395
396         return false;
397
398
399 /**
400  Convert a string to lower case, allocated with talloc
401 **/
402 _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
403 {
404         size_t size=0;
405         char *dest;
406         struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
407
408         /* this takes advantage of the fact that upper/lower can't
409            change the length of a character by more than 1 byte */
410         dest = talloc_array(ctx, char, 2*(strlen(src))+1);
411         if (dest == NULL) {
412                 return NULL;
413         }
414
415         while (*src) {
416                 size_t c_size;
417                 codepoint_t c = next_codepoint(iconv_convenience, src, &c_size);
418                 src += c_size;
419
420                 c = tolower_m(c);
421
422                 c_size = push_codepoint(iconv_convenience, dest+size, c);
423                 if (c_size == -1) {
424                         talloc_free(dest);
425                         return NULL;
426                 }
427                 size += c_size;
428         }
429
430         dest[size] = 0;
431
432         /* trim it so talloc_append_string() works */
433         dest = talloc_realloc(ctx, dest, char, size+1);
434
435         talloc_set_name_const(dest, dest);
436
437         return dest;
438 }
439
440 /**
441  Convert a string to UPPER case, allocated with talloc
442  source length limited to n bytes
443 **/
444 _PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n)
445 {
446         size_t size=0;
447         char *dest;
448         struct smb_iconv_convenience *iconv_convenience = get_iconv_convenience();
449         
450         if (!src) {
451                 return NULL;
452         }
453
454         /* this takes advantage of the fact that upper/lower can't
455            change the length of a character by more than 1 byte */
456         dest = talloc_array(ctx, char, 2*(n+1));
457         if (dest == NULL) {
458                 return NULL;
459         }
460
461         while (*src && n--) {
462                 size_t c_size;
463                 codepoint_t c = next_codepoint(iconv_convenience, src, &c_size);
464                 src += c_size;
465
466                 c = toupper_m(c);
467
468                 c_size = push_codepoint(iconv_convenience, dest+size, c);
469                 if (c_size == -1) {
470                         talloc_free(dest);
471                         return NULL;
472                 }
473                 size += c_size;
474         }
475
476         dest[size] = 0;
477
478         /* trim it so talloc_append_string() works */
479         dest = talloc_realloc(ctx, dest, char, size+1);
480
481         talloc_set_name_const(dest, dest);
482
483         return dest;
484 }
485
486 /**
487  Convert a string to UPPER case, allocated with talloc
488 **/
489 _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
490 {
491         return strupper_talloc_n(ctx, src, src?strlen(src):0);
492 }
493
494 /**
495  talloc_strdup() a unix string to upper case.
496 **/
497 _PUBLIC_ char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *src)
498 {
499         return strupper_talloc(ctx, src);
500 }
501
502 /**
503  Convert a string to lower case.
504 **/
505 _PUBLIC_ void strlower_m(char *s)
506 {
507         char *d;
508         struct smb_iconv_convenience *iconv_convenience;
509
510         /* this is quite a common operation, so we want it to be
511            fast. We optimise for the ascii case, knowing that all our
512            supported multi-byte character sets are ascii-compatible
513            (ie. they match for the first 128 chars) */
514         while (*s && !(((uint8_t)*s) & 0x80)) {
515                 *s = tolower((uint8_t)*s);
516                 s++;
517         }
518
519         if (!*s)
520                 return;
521
522         iconv_convenience = get_iconv_convenience();
523
524         d = s;
525
526         while (*s) {
527                 size_t c_size, c_size2;
528                 codepoint_t c = next_codepoint(iconv_convenience, s, &c_size);
529                 c_size2 = push_codepoint(iconv_convenience, d, tolower_m(c));
530                 if (c_size2 > c_size) {
531                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
532                                  c, tolower_m(c), (int)c_size, (int)c_size2));
533                         smb_panic("codepoint expansion in strlower_m\n");
534                 }
535                 s += c_size;
536                 d += c_size2;
537         }
538         *d = 0;
539 }
540
541 /**
542  Convert a string to UPPER case.
543 **/
544 _PUBLIC_ void strupper_m(char *s)
545 {
546         char *d;
547         struct smb_iconv_convenience *iconv_convenience;
548
549         /* this is quite a common operation, so we want it to be
550            fast. We optimise for the ascii case, knowing that all our
551            supported multi-byte character sets are ascii-compatible
552            (ie. they match for the first 128 chars) */
553         while (*s && !(((uint8_t)*s) & 0x80)) {
554                 *s = toupper((uint8_t)*s);
555                 s++;
556         }
557
558         if (!*s)
559                 return;
560
561         iconv_convenience = get_iconv_convenience();
562
563         d = s;
564
565         while (*s) {
566                 size_t c_size, c_size2;
567                 codepoint_t c = next_codepoint(iconv_convenience, s, &c_size);
568                 c_size2 = push_codepoint(iconv_convenience, d, toupper_m(c));
569                 if (c_size2 > c_size) {
570                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
571                                  c, toupper_m(c), (int)c_size, (int)c_size2));
572                         smb_panic("codepoint expansion in strupper_m\n");
573                 }
574                 s += c_size;
575                 d += c_size2;
576         }
577         *d = 0;
578 }
579
580
581 /**
582  Find the number of 'c' chars in a string
583 **/
584 _PUBLIC_ size_t count_chars_m(const char *s, char c)
585 {
586         size_t count = 0;
587
588         while (*s) {
589                 size_t size;
590                 codepoint_t c2 = next_codepoint(get_iconv_convenience(), s, &size);
591                 if (c2 == c) count++;
592                 s += size;
593         }
594
595         return count;
596 }
597
598
599 /**
600  * Copy a string from a char* unix src to a dos codepage string destination.
601  *
602  * @return the number of bytes occupied by the string in the destination.
603  *
604  * @param flags can include
605  * <dl>
606  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
607  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
608  * </dl>
609  *
610  * @param dest_len the maximum length in bytes allowed in the
611  * destination.  If @p dest_len is -1 then no maximum is used.
612  **/
613 static ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
614 {
615         size_t src_len;
616         ssize_t ret;
617         struct smb_iconv_convenience *ic = get_iconv_convenience();
618
619         if (flags & STR_UPPER) {
620                 char *tmpbuf = strupper_talloc(NULL, src);
621                 if (tmpbuf == NULL) {
622                         return -1;
623                 }
624                 ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
625                 talloc_free(tmpbuf);
626                 return ret;
627         }
628
629         src_len = strlen(src);
630
631         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
632                 src_len++;
633
634         return convert_string(ic, CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
635 }
636
637 /**
638  * Copy a string from a unix char* src to an ASCII destination,
639  * allocating a buffer using talloc().
640  *
641  * @param dest always set at least to NULL 
642  *
643  * @returns The number of bytes occupied by the string in the destination
644  *         or -1 in case of error.
645  **/
646 _PUBLIC_ ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
647 {
648         struct smb_iconv_convenience *ic = get_iconv_convenience();
649         size_t src_len = strlen(src)+1;
650         *dest = NULL;
651         return convert_string_talloc(ctx, ic, CH_UNIX, CH_DOS, src, src_len, (void **)dest);
652 }
653
654
655 /**
656  * Copy a string from a dos codepage source to a unix char* destination.
657  *
658  * The resulting string in "dest" is always null terminated.
659  *
660  * @param flags can have:
661  * <dl>
662  * <dt>STR_TERMINATE</dt>
663  * <dd>STR_TERMINATE means the string in @p src
664  * is null terminated, and src_len is ignored.</dd>
665  * </dl>
666  *
667  * @param src_len is the length of the source area in bytes.
668  * @returns the number of bytes occupied by the string in @p src.
669  **/
670 static ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
671 {
672         struct smb_iconv_convenience *ic = get_iconv_convenience();
673         size_t ret;
674
675         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
676                 if (src_len == (size_t)-1) {
677                         src_len = strlen((const char *)src) + 1;
678                 } else {
679                         size_t len = strnlen((const char *)src, src_len);
680                         if (len < src_len)
681                                 len++;
682                         src_len = len;
683                 }
684         }
685
686         ret = convert_string(ic, CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
687
688         if (dest_len)
689                 dest[MIN(ret, dest_len-1)] = 0;
690
691         return src_len;
692 }
693
694 /**
695  * Copy a string from a char* src to a unicode destination.
696  *
697  * @returns the number of bytes occupied by the string in the destination.
698  *
699  * @param flags can have:
700  *
701  * <dl>
702  * <dt>STR_TERMINATE <dd>means include the null termination.
703  * <dt>STR_UPPER     <dd>means uppercase in the destination.
704  * <dt>STR_NOALIGN   <dd>means don't do alignment.
705  * </dl>
706  *
707  * @param dest_len is the maximum length allowed in the
708  * destination. If dest_len is -1 then no maxiumum is used.
709  **/
710 static ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags)
711 {
712         struct smb_iconv_convenience *ic = get_iconv_convenience();
713         size_t len=0;
714         size_t src_len = strlen(src);
715         size_t ret;
716
717         if (flags & STR_UPPER) {
718                 char *tmpbuf = strupper_talloc(NULL, src);
719                 if (tmpbuf == NULL) {
720                         return -1;
721                 }
722                 ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
723                 talloc_free(tmpbuf);
724                 return ret;
725         }
726
727         if (flags & STR_TERMINATE)
728                 src_len++;
729
730         if (ucs2_align(NULL, dest, flags)) {
731                 *(char *)dest = 0;
732                 dest = (void *)((char *)dest + 1);
733                 if (dest_len) dest_len--;
734                 len++;
735         }
736
737         /* ucs2 is always a multiple of 2 bytes */
738         dest_len &= ~1;
739
740         ret = convert_string(ic, CH_UNIX, CH_UTF16, src, src_len, dest, dest_len);
741         if (ret == (size_t)-1) {
742                 return 0;
743         }
744
745         len += ret;
746
747         return len;
748 }
749
750
751 /**
752  * Copy a string from a unix char* src to a UCS2 destination,
753  * allocating a buffer using talloc().
754  *
755  * @param dest always set at least to NULL 
756  *
757  * @returns The number of bytes occupied by the string in the destination
758  *         or -1 in case of error.
759  **/
760 _PUBLIC_ ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
761 {
762         struct smb_iconv_convenience *ic = get_iconv_convenience();
763         size_t src_len = strlen(src)+1;
764         *dest = NULL;
765         return convert_string_talloc(ctx, ic, CH_UNIX, CH_UTF16, src, src_len, dest);
766 }
767
768
769 /**
770  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
771  *
772  * @param dest always set at least to NULL 
773  *
774  * @returns The number of bytes occupied by the string in the destination
775  **/
776
777 _PUBLIC_ ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
778 {
779         struct smb_iconv_convenience *ic = get_iconv_convenience();
780         size_t src_len = strlen(src)+1;
781         *dest = NULL;
782         return convert_string_talloc(ctx, ic, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
783 }
784
785 /**
786  Copy a string from a ucs2 source to a unix char* destination.
787  Flags can have:
788   STR_TERMINATE means the string in src is null terminated.
789   STR_NOALIGN   means don't try to align.
790  if STR_TERMINATE is set then src_len is ignored if it is -1.
791  src_len is the length of the source area in bytes
792  Return the number of bytes occupied by the string in src.
793  The resulting string in "dest" is always null terminated.
794 **/
795
796 static size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
797 {
798         struct smb_iconv_convenience *ic = get_iconv_convenience();
799         size_t ret;
800
801         if (ucs2_align(NULL, src, flags)) {
802                 src = (const void *)((const char *)src + 1);
803                 if (src_len > 0)
804                         src_len--;
805         }
806
807         if (flags & STR_TERMINATE) {
808                 if (src_len == (size_t)-1) {
809                         src_len = utf16_len(src);
810                 } else {
811                         src_len = utf16_len_n(src, src_len);
812                 }
813         }
814
815         /* ucs2 is always a multiple of 2 bytes */
816         if (src_len != (size_t)-1)
817                 src_len &= ~1;
818         
819         ret = convert_string(ic, CH_UTF16, CH_UNIX, src, src_len, dest, dest_len);
820         if (dest_len)
821                 dest[MIN(ret, dest_len-1)] = 0;
822
823         return src_len;
824 }
825
826 /**
827  * Copy a string from a ASCII src to a unix char * destination, allocating a buffer using talloc
828  *
829  * @param dest always set at least to NULL 
830  *
831  * @returns The number of bytes occupied by the string in the destination
832  **/
833
834 _PUBLIC_ ssize_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
835 {
836         struct smb_iconv_convenience *ic = get_iconv_convenience();
837         size_t src_len = strlen(src)+1;
838         *dest = NULL;
839         return convert_string_talloc(ctx, ic, CH_DOS, CH_UNIX, src, src_len, (void **)dest);
840 }
841
842 /**
843  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
844  *
845  * @param dest always set at least to NULL 
846  *
847  * @returns The number of bytes occupied by the string in the destination
848  **/
849
850 _PUBLIC_ ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src)
851 {
852         struct smb_iconv_convenience *ic = get_iconv_convenience();
853         size_t src_len = utf16_len(src);
854         *dest = NULL;
855         return convert_string_talloc(ctx, ic, CH_UTF16, CH_UNIX, src, src_len, (void **)dest);
856 }
857
858 /**
859  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
860  *
861  * @param dest always set at least to NULL 
862  *
863  * @returns The number of bytes occupied by the string in the destination
864  **/
865
866 _PUBLIC_ ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
867 {
868         struct smb_iconv_convenience *ic = get_iconv_convenience();
869         size_t src_len = strlen(src)+1;
870         *dest = NULL;
871         return convert_string_talloc(ctx, ic, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
872 }
873
874 /**
875  Copy a string from a char* src to a unicode or ascii
876  dos codepage destination choosing unicode or ascii based on the 
877  flags in the SMB buffer starting at base_ptr.
878  Return the number of bytes occupied by the string in the destination.
879  flags can have:
880   STR_TERMINATE means include the null termination.
881   STR_UPPER     means uppercase in the destination.
882   STR_ASCII     use ascii even with unicode packet.
883   STR_NOALIGN   means don't do alignment.
884  dest_len is the maximum length allowed in the destination. If dest_len
885  is -1 then no maxiumum is used.
886 **/
887
888 _PUBLIC_ ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
889 {
890         if (flags & STR_ASCII) {
891                 return push_ascii(dest, src, dest_len, flags);
892         } else if (flags & STR_UNICODE) {
893                 return push_ucs2(dest, src, dest_len, flags);
894         } else {
895                 smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set");
896                 return -1;
897         }
898 }
899
900
901 /**
902  Copy a string from a unicode or ascii source (depending on
903  the packet flags) to a char* destination.
904  Flags can have:
905   STR_TERMINATE means the string in src is null terminated.
906   STR_UNICODE   means to force as unicode.
907   STR_ASCII     use ascii even with unicode packet.
908   STR_NOALIGN   means don't do alignment.
909  if STR_TERMINATE is set then src_len is ignored is it is -1
910  src_len is the length of the source area in bytes.
911  Return the number of bytes occupied by the string in src.
912  The resulting string in "dest" is always null terminated.
913 **/
914
915 _PUBLIC_ ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
916 {
917         if (flags & STR_ASCII) {
918                 return pull_ascii(dest, src, dest_len, src_len, flags);
919         } else if (flags & STR_UNICODE) {
920                 return pull_ucs2(dest, src, dest_len, src_len, flags);
921         } else {
922                 smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set");
923                 return -1;
924         }
925 }
926
927