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