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