a8df003f8bca63d030466b42cce2792bd5af3924
[kai/samba.git] / source3 / lib / charcnv.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Character set conversion Extensions
4    Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5    Copyright (C) Andrew Tridgell 2001
6    Copyright (C) Simo Sorce 2001
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23 #include "includes.h"
24
25 /**
26  * @file
27  *
28  * @brief Character-set conversion routines built on our iconv.
29  * 
30  * @note Samba's internal character set (at least in the 3.0 series)
31  * is always the same as the one for the Unix filesystem.  It is
32  * <b>not</b> necessarily UTF-8 and may be different on machines that
33  * need i18n filenames to be compatible with Unix software.  It does
34  * have to be a superset of ASCII.  All multibyte sequences must start
35  * with a byte with the high bit set.
36  *
37  * @sa lib/iconv.c
38  */
39
40 static pstring cvtbuf;
41
42 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
43
44
45 /**
46  * Return the name of a charset to give to iconv().
47  **/
48 static const char *charset_name(charset_t ch)
49 {
50         const char *ret = NULL;
51
52         if (ch == CH_UCS2) ret = "UCS-2LE";
53         else if (ch == CH_UNIX) ret = lp_unix_charset();
54         else if (ch == CH_DOS) ret = lp_dos_charset();
55         else if (ch == CH_DISPLAY) ret = lp_display_charset();
56         else if (ch == CH_UTF8) ret = "UTF8";
57
58         if (!ret || !*ret) ret = "ASCII";
59         return ret;
60 }
61
62 static void lazy_initialize_conv(void)
63 {
64         static int initialized = False;
65
66         if (!initialized) {
67                 initialized = True;
68                 load_case_tables();
69                 init_iconv();
70                 init_valid_table();
71         }
72 }
73
74 /**
75  Initialize iconv conversion descriptors.
76 **/
77
78 void init_iconv(void)
79 {
80         int c1, c2;
81         BOOL did_reload = False;
82
83         /* so that charset_name() works we need to get the UNIX<->UCS2 going
84            first */
85         if (!conv_handles[CH_UNIX][CH_UCS2])
86                 conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII");
87
88         if (!conv_handles[CH_UCS2][CH_UNIX])
89                 conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE");
90
91         for (c1=0;c1<NUM_CHARSETS;c1++) {
92                 for (c2=0;c2<NUM_CHARSETS;c2++) {
93                         const char *n1 = charset_name((charset_t)c1);
94                         const char *n2 = charset_name((charset_t)c2);
95                         if (conv_handles[c1][c2] &&
96                             strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
97                             strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
98                                 continue;
99
100                         did_reload = True;
101
102                         if (conv_handles[c1][c2])
103                                 smb_iconv_close(conv_handles[c1][c2]);
104
105                         conv_handles[c1][c2] = smb_iconv_open(n2,n1);
106                         if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
107                                 DEBUG(0,("Conversion from %s to %s not supported\n",
108                                          charset_name((charset_t)c1), charset_name((charset_t)c2)));
109                                 conv_handles[c1][c2] = NULL;
110                         }
111                 }
112         }
113
114         if (did_reload) {
115                 init_valid_table();
116         }
117 }
118
119 /**
120  * Convert string from one encoding to another, making error checking etc
121  *
122  * @param src pointer to source string (multibyte or singlebyte)
123  * @param srclen length of the source string in bytes
124  * @param dest pointer to destination string (multibyte or singlebyte)
125  * @param destlen maximal length allowed for string
126  * @returns the number of bytes occupied in the destination
127  **/
128 size_t convert_string(charset_t from, charset_t to,
129                       void const *src, size_t srclen, 
130                       void *dest, size_t destlen)
131 {
132         size_t i_len, o_len;
133         size_t retval;
134         const char* inbuf = (const char*)src;
135         char* outbuf = (char*)dest;
136         smb_iconv_t descriptor;
137
138         if (srclen == (size_t)-1)
139                 srclen = strlen(src)+1;
140
141         lazy_initialize_conv();
142
143         descriptor = conv_handles[from][to];
144
145         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
146                 /* conversion not supported, use as is */
147                 size_t len = MIN(srclen,destlen);
148                 memcpy(dest,src,len);
149                 return len;
150         }
151
152         i_len=srclen;
153         o_len=destlen;
154         retval = smb_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
155         if(retval==(size_t)-1) {
156                 const char *reason="unknown error";
157                 switch(errno) {
158                         case EINVAL:
159                                 reason="Incomplete multibyte sequence";
160                                 break;
161                         case E2BIG:
162                                 reason="No more room"; 
163                                 DEBUG(0, ("convert_string: Required %d, available %d\n",
164                                         srclen, destlen));
165                                 /* we are not sure we need srclen bytes,
166                                   may be more, may be less.
167                                   We only know we need more than destlen
168                                   bytes ---simo */
169                                break;
170                         case EILSEQ:
171                                reason="Illegal multibyte sequence";
172                                break;
173                 }
174                 /* smb_panic(reason); */
175         }
176         return destlen-o_len;
177 }
178
179 /**
180  * Convert between character sets, allocating a new buffer for the result.
181  *
182  * @param srclen length of source buffer.
183  * @param dest always set at least to NULL
184  * @note -1 is not accepted for srclen.
185  *
186  * @returns Size in bytes of the converted string; or -1 in case of error.
187  **/
188
189 size_t convert_string_allocate(charset_t from, charset_t to,
190                                 void const *src, size_t srclen, void **dest)
191 {
192         size_t i_len, o_len, destlen;
193         size_t retval;
194         const char *inbuf = (const char *)src;
195         char *outbuf, *ob;
196         smb_iconv_t descriptor;
197
198         *dest = NULL;
199
200         if (src == NULL || srclen == (size_t)-1)
201                 return (size_t)-1;
202
203         lazy_initialize_conv();
204
205         descriptor = conv_handles[from][to];
206
207         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
208                 /* conversion not supported, return -1*/
209                 DEBUG(3, ("convert_string_allocate: conversion not supported!\n"));
210                 return -1;
211         }
212
213         destlen = MAX(srclen, 512);
214         outbuf = NULL;
215 convert:
216         destlen = destlen * 2;
217         ob = (char *)realloc(outbuf, destlen);
218         if (!ob) {
219                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
220                 SAFE_FREE(outbuf);
221                 return (size_t)-1;
222         }
223         else
224                 outbuf = ob;
225         i_len = srclen;
226         o_len = destlen;
227         retval = smb_iconv(descriptor,
228                            &inbuf, &i_len,
229                            &outbuf, &o_len);
230         if(retval == (size_t)-1)                {
231                 const char *reason="unknown error";
232                 switch(errno) {
233                         case EINVAL:
234                                 reason="Incomplete multibyte sequence";
235                                 break;
236                         case E2BIG:
237                                 goto convert;           
238                         case EILSEQ:
239                                 reason="Illegal multibyte sequence";
240                                 break;
241                 }
242                 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
243                 /* smb_panic(reason); */
244                 return (size_t)-1;
245         }
246         
247         destlen = destlen - o_len;
248         *dest = (char *)Realloc(ob,destlen);
249         if (!*dest) {
250                 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
251                 SAFE_FREE(ob);
252                 return (size_t)-1;
253         }
254
255         return destlen;
256 }
257
258
259 /**
260  * Convert between character sets, allocating a new buffer using talloc for the result.
261  *
262  * @param srclen length of source buffer.
263  * @param dest always set at least to NULL 
264  * @note -1 is not accepted for srclen.
265  *
266  * @returns Size in bytes of the converted string; or -1 in case of error.
267  **/
268 size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
269                                 void const *src, size_t srclen, void **dest)
270 {
271         void *alloced_string;
272         size_t dest_len;
273
274         *dest = NULL;
275         dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string);
276         if (dest_len == (size_t)-1)
277                 return (size_t)-1;
278         *dest = talloc_memdup(ctx, alloced_string, dest_len);
279         SAFE_FREE(alloced_string);
280         if (*dest == NULL)
281                 return (size_t)-1;
282         return dest_len;
283 }
284
285 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
286 {
287         size_t size;
288         smb_ucs2_t *buffer=(smb_ucs2_t*)cvtbuf;
289         size=convert_string(CH_UNIX, CH_UCS2, src, srclen, buffer, sizeof(cvtbuf));
290         if (!strupper_w(buffer) && (dest == src))
291                 return srclen;
292         return convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
293 }
294
295 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
296 {
297         size_t size;
298         smb_ucs2_t *buffer=(smb_ucs2_t*)cvtbuf;
299         size=convert_string(CH_UNIX, CH_UCS2, src, srclen, buffer, sizeof(cvtbuf));
300         if (!strlower_w(buffer) && (dest == src))
301                 return srclen;
302         return convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
303 }
304
305
306 size_t ucs2_align(const void *base_ptr, const void *p, int flags)
307 {
308         if (flags & (STR_NOALIGN|STR_ASCII))
309                 return 0;
310         return PTR_DIFF(p, base_ptr) & 1;
311 }
312
313
314 /**
315  * Copy a string from a char* unix src to a dos codepage string destination.
316  *
317  * @return the number of bytes occupied by the string in the destination.
318  *
319  * @param flags can include
320  * <dl>
321  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
322  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
323  * </dl>
324  *
325  * @param dest_len the maximum length in bytes allowed in the
326  * destination.  If @p dest_len is -1 then no maximum is used.
327  **/
328 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
329 {
330         size_t src_len = strlen(src);
331         pstring tmpbuf;
332
333         /* treat a pstring as "unlimited" length */
334         if (dest_len == (size_t)-1)
335                 dest_len = sizeof(pstring);
336
337         if (flags & STR_UPPER) {
338                 pstrcpy(tmpbuf, src);
339                 strupper(tmpbuf);
340                 src = tmpbuf;
341         }
342
343         if (flags & STR_TERMINATE)
344                 src_len++;
345
346         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
347 }
348
349 size_t push_ascii_fstring(void *dest, const char *src)
350 {
351         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
352 }
353
354 size_t push_ascii_pstring(void *dest, const char *src)
355 {
356         return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
357 }
358
359 size_t push_pstring(void *dest, const char *src)
360 {
361         return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
362 }
363
364 /**
365  * Copy a string from a dos codepage source to a unix char* destination.
366  *
367  * The resulting string in "dest" is always null terminated.
368  *
369  * @param flags can have:
370  * <dl>
371  * <dt>STR_TERMINATE</dt>
372  * <dd>STR_TERMINATE means the string in @p src
373  * is null terminated, and src_len is ignored.</dd>
374  * </dl>
375  *
376  * @param src_len is the length of the source area in bytes.
377  * @returns the number of bytes occupied by the string in @p src.
378  **/
379 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
380 {
381         size_t ret;
382
383         if (dest_len == (size_t)-1)
384                 dest_len = sizeof(pstring);
385
386         if (flags & STR_TERMINATE) {
387                 if (src_len == (size_t)-1) {
388                         src_len = strlen(src) + 1;
389                 } else {
390                         size_t len = strnlen(src, src_len);
391                         if (len < src_len)
392                                 len++;
393                         src_len = len;
394                 }
395         }
396
397         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
398
399         if (dest_len)
400                 dest[MIN(ret, dest_len-1)] = 0;
401
402         return src_len;
403 }
404
405 size_t pull_ascii_pstring(char *dest, const void *src)
406 {
407         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
408 }
409
410 size_t pull_ascii_fstring(char *dest, const void *src)
411 {
412         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
413 }
414
415 /**
416  * Copy a string from a char* src to a unicode destination.
417  *
418  * @returns the number of bytes occupied by the string in the destination.
419  *
420  * @param flags can have:
421  *
422  * <dl>
423  * <dt>STR_TERMINATE <dd>means include the null termination.
424  * <dt>STR_UPPER     <dd>means uppercase in the destination.
425  * <dt>STR_NOALIGN   <dd>means don't do alignment.
426  * </dl>
427  *
428  * @param dest_len is the maximum length allowed in the
429  * destination. If dest_len is -1 then no maxiumum is used.
430  **/
431 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
432 {
433         size_t len=0;
434         size_t src_len = strlen(src);
435         pstring tmpbuf;
436
437         /* treat a pstring as "unlimited" length */
438         if (dest_len == (size_t)-1)
439                 dest_len = sizeof(pstring);
440
441         if (flags & STR_UPPER) {
442                 pstrcpy(tmpbuf, src);
443                 strupper(tmpbuf);
444                 src = tmpbuf;
445         }
446
447         if (flags & STR_TERMINATE)
448                 src_len++;
449
450         if (ucs2_align(base_ptr, dest, flags)) {
451                 *(char *)dest = 0;
452                 dest = (void *)((char *)dest + 1);
453                 if (dest_len) dest_len--;
454                 len++;
455         }
456
457         /* ucs2 is always a multiple of 2 bytes */
458         dest_len &= ~1;
459
460         len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
461         return len;
462 }
463
464
465 /**
466  * Copy a string from a unix char* src to a UCS2 destination,
467  * allocating a buffer using talloc().
468  *
469  * @param dest always set at least to NULL 
470  *
471  * @returns The number of bytes occupied by the string in the destination
472  *         or -1 in case of error.
473  **/
474 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
475 {
476         size_t src_len = strlen(src)+1;
477
478         *dest = NULL;
479         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
480 }
481
482
483 /**
484  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
485  *
486  * @param dest always set at least to NULL 
487  *
488  * @returns The number of bytes occupied by the string in the destination
489  *         or -1 in case of error.
490  **/
491
492 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
493 {
494         size_t src_len = strlen(src)+1;
495
496         *dest = NULL;
497         return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest);  
498 }
499
500 /**
501  Copy a string from a char* src to a UTF-8 destination.
502  Return the number of bytes occupied by the string in the destination
503  Flags can have:
504   STR_TERMINATE means include the null termination
505   STR_UPPER     means uppercase in the destination
506  dest_len is the maximum length allowed in the destination. If dest_len
507  is -1 then no maxiumum is used.
508 **/
509
510 size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
511 {
512         size_t src_len = strlen(src);
513         pstring tmpbuf;
514
515         /* treat a pstring as "unlimited" length */
516         if (dest_len == (size_t)-1)
517                 dest_len = sizeof(pstring);
518
519         if (flags & STR_UPPER) {
520                 pstrcpy(tmpbuf, src);
521                 strupper(tmpbuf);
522                 src = tmpbuf;
523         }
524
525         if (flags & STR_TERMINATE)
526                 src_len++;
527
528         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
529 }
530
531 size_t push_utf8_fstring(void *dest, const char *src)
532 {
533         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
534 }
535
536 size_t push_utf8_pstring(void *dest, const char *src)
537 {
538         return push_utf8(dest, src, sizeof(pstring), STR_TERMINATE);
539 }
540
541 /**
542  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
543  *
544  * @param dest always set at least to NULL 
545  *
546  * @returns The number of bytes occupied by the string in the destination
547  **/
548
549 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
550 {
551         size_t src_len = strlen(src)+1;
552
553         *dest = NULL;
554         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
555 }
556
557 /**
558  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
559  *
560  * @param dest always set at least to NULL 
561  *
562  * @returns The number of bytes occupied by the string in the destination
563  **/
564
565 size_t push_utf8_allocate(char **dest, const char *src)
566 {
567         size_t src_len = strlen(src)+1;
568
569         *dest = NULL;
570         return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest);  
571 }
572
573 /**
574  Copy a string from a ucs2 source to a unix char* destination.
575  Flags can have:
576   STR_TERMINATE means the string in src is null terminated.
577   STR_NOALIGN   means don't try to align.
578  if STR_TERMINATE is set then src_len is ignored if it is -1.
579  src_len is the length of the source area in bytes
580  Return the number of bytes occupied by the string in src.
581  The resulting string in "dest" is always null terminated.
582 **/
583
584 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
585 {
586         size_t ret;
587
588         if (dest_len == (size_t)-1)
589                 dest_len = sizeof(pstring);
590
591         if (ucs2_align(base_ptr, src, flags)) {
592                 src = (const void *)((const char *)src + 1);
593                 if (src_len > 0)
594                         src_len--;
595         }
596
597         if (flags & STR_TERMINATE) {
598                 if (src_len == (size_t)-1) {
599                         src_len = strlen_w(src)*2 + 2;
600                 } else {
601                         size_t len = strnlen_w(src, src_len/2);
602                         if (len < src_len/2)
603                                 len++;
604                         src_len = len*2;
605                 }
606         }
607
608         /* ucs2 is always a multiple of 2 bytes */
609         if (src_len != (size_t)-1)
610                 src_len &= ~1;
611         
612         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
613         if (dest_len)
614                 dest[MIN(ret, dest_len-1)] = 0;
615
616         return src_len;
617 }
618
619 size_t pull_ucs2_pstring(char *dest, const void *src)
620 {
621         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
622 }
623
624 size_t pull_ucs2_fstring(char *dest, const void *src)
625 {
626         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
627 }
628
629 /**
630  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
631  *
632  * @param dest always set at least to NULL 
633  *
634  * @returns The number of bytes occupied by the string in the destination
635  **/
636
637 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
638 {
639         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
640         *dest = NULL;
641         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
642 }
643
644 /**
645  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
646  *
647  * @param dest always set at least to NULL 
648  *
649  * @returns The number of bytes occupied by the string in the destination
650  **/
651
652 size_t pull_ucs2_allocate(void **dest, const smb_ucs2_t *src)
653 {
654         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
655         *dest = NULL;
656         return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, dest);   
657 }
658
659 /**
660  Copy a string from a utf-8 source to a unix char* destination.
661  Flags can have:
662   STR_TERMINATE means the string in src is null terminated.
663  if STR_TERMINATE is set then src_len is ignored.
664  src_len is the length of the source area in bytes
665  Return the number of bytes occupied by the string in src.
666  The resulting string in "dest" is always null terminated.
667 **/
668
669 size_t pull_utf8(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
670 {
671         size_t ret;
672
673         if (dest_len == (size_t)-1)
674                 dest_len = sizeof(pstring);
675
676         if (flags & STR_TERMINATE) {
677                 if (src_len == (size_t)-1) {
678                         src_len = strlen(src) + 1;
679                 } else {
680                         size_t len = strnlen(src, src_len);
681                         if (len < src_len)
682                                 len++;
683                         src_len = len;
684                 }
685         }
686
687         ret = convert_string(CH_UTF8, CH_UNIX, src, src_len, dest, dest_len);
688         if (dest_len)
689                 dest[MIN(ret, dest_len-1)] = 0;
690
691         return src_len;
692 }
693
694 size_t pull_utf8_pstring(char *dest, const void *src)
695 {
696         return pull_utf8(dest, src, sizeof(pstring), -1, STR_TERMINATE);
697 }
698
699 size_t pull_utf8_fstring(char *dest, const void *src)
700 {
701         return pull_utf8(dest, src, sizeof(fstring), -1, STR_TERMINATE);
702 }
703
704 /**
705  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
706  *
707  * @param dest always set at least to NULL 
708  *
709  * @returns The number of bytes occupied by the string in the destination
710  **/
711
712 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
713 {
714         size_t src_len = strlen(src)+1;
715         *dest = NULL;
716         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);       
717 }
718
719 /**
720  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
721  *
722  * @param dest always set at least to NULL 
723  *
724  * @returns The number of bytes occupied by the string in the destination
725  **/
726
727 size_t pull_utf8_allocate(void **dest, const char *src)
728 {
729         size_t src_len = strlen(src)+1;
730         *dest = NULL;
731         return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest);   
732 }
733  
734 /**
735  Copy a string from a char* src to a unicode or ascii
736  dos codepage destination choosing unicode or ascii based on the 
737  flags in the SMB buffer starting at base_ptr.
738  Return the number of bytes occupied by the string in the destination.
739  flags can have:
740   STR_TERMINATE means include the null termination.
741   STR_UPPER     means uppercase in the destination.
742   STR_ASCII     use ascii even with unicode packet.
743   STR_NOALIGN   means don't do alignment.
744  dest_len is the maximum length allowed in the destination. If dest_len
745  is -1 then no maxiumum is used.
746 **/
747
748 size_t push_string(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
749 {
750         if (!(flags & STR_ASCII) && \
751             ((flags & STR_UNICODE || \
752               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
753                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
754         }
755         return push_ascii(dest, src, dest_len, flags);
756 }
757
758
759 /**
760  Copy a string from a unicode or ascii source (depending on
761  the packet flags) to a char* destination.
762  Flags can have:
763   STR_TERMINATE means the string in src is null terminated.
764   STR_UNICODE   means to force as unicode.
765   STR_ASCII     use ascii even with unicode packet.
766   STR_NOALIGN   means don't do alignment.
767  if STR_TERMINATE is set then src_len is ignored is it is -1
768  src_len is the length of the source area in bytes.
769  Return the number of bytes occupied by the string in src.
770  The resulting string in "dest" is always null terminated.
771 **/
772
773 size_t pull_string(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
774 {
775         if (!(flags & STR_ASCII) && \
776             ((flags & STR_UNICODE || \
777               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
778                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
779         }
780         return pull_ascii(dest, src, dest_len, src_len, flags);
781 }
782
783 size_t align_string(const void *base_ptr, const char *p, int flags)
784 {
785         if (!(flags & STR_ASCII) && \
786             ((flags & STR_UNICODE || \
787               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
788                 return ucs2_align(base_ptr, p, flags);
789         }
790         return 0;
791 }
792
793 /**
794  Convert from ucs2 to unix charset and return the
795  allocated and converted string or NULL if an error occurred.
796  You must provide a zero terminated string.
797  The returning string will be zero terminated.
798 **/
799
800 char *acnv_u2ux(const smb_ucs2_t *src)
801 {
802         size_t slen;
803         size_t dlen;
804         void *dest;
805         
806         slen = (strlen_w(src) + 1) * sizeof(smb_ucs2_t);
807         dlen = convert_string_allocate(CH_UCS2, CH_UNIX, src, slen, &dest);
808         if (dlen == (size_t)-1)
809                 return NULL;
810         else
811                 return dest;
812 }
813
814 /**
815  Convert from unix to ucs2 charset and return the
816  allocated and converted string or NULL if an error occurred.
817  You must provide a zero terminated string.
818  The returning string will be zero terminated.
819 **/
820
821 smb_ucs2_t *acnv_uxu2(const char *src)
822 {
823         size_t slen;
824         size_t dlen;
825         void *dest;
826         
827         slen = strlen(src) + 1;
828         dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest);
829         if (dlen == (size_t)-1)
830                 return NULL;
831         else
832                 return dest;
833 }
834
835 /**
836  Convert from ucs2 to dos charset and return the
837  allocated and converted string or NULL if an error occurred.
838  You must provide a zero terminated string.
839  The returning string will be zero terminated.
840 **/
841
842 char *acnv_u2dos(const smb_ucs2_t *src)
843 {
844         size_t slen;
845         size_t dlen;
846         void *dest;
847         
848         slen = (strlen_w(src) + 1) * sizeof(smb_ucs2_t);
849         dlen = convert_string_allocate(CH_UCS2, CH_DOS, src, slen, &dest);
850         if (dlen == (size_t)-1)
851                 return NULL;
852         else
853                 return dest;
854 }
855
856 /**
857  Convert from dos to ucs2 charset and return the
858  allocated and converted string or NULL if an error occurred.
859  You must provide a zero terminated string.
860  The returning string will be zero terminated.
861 **/
862
863 smb_ucs2_t *acnv_dosu2(const char *src)
864 {
865         size_t slen;
866         size_t dlen;
867         void *dest;
868         
869         slen = strlen(src) + 1;
870         dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest);
871         if (dlen == (size_t)-1)
872                 return NULL;
873         else
874                 return dest;
875 }