port latest changes from SAMBA_3_0 tree
[vlendec/samba-autobuild/.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 %lu, available %lu\n",
194                                         (unsigned long)srclen, (unsigned long)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 = push_ucs2_allocate(&buffer, src);
323         if (size == -1) {
324                 smb_panic("failed to create UCS2 buffer");
325         }
326         if (!strupper_w(buffer) && (dest == src)) {
327                 free(buffer);
328                 return srclen;
329         }
330         
331         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
332         free(buffer);
333         return size;
334 }
335
336 /**
337  strdup() a unix string to upper case.
338 **/
339
340 char *strdup_upper(const char *s)
341 {
342         size_t size;
343         smb_ucs2_t *buffer;
344         char *out_buffer;
345         
346         size = push_ucs2_allocate(&buffer, s);
347         if (size == -1) {
348                 return NULL;
349         }
350
351         strupper_w(buffer);
352         
353         size = pull_ucs2_allocate(&out_buffer, buffer);
354         SAFE_FREE(buffer);
355
356         if (size == -1) {
357                 return NULL;
358         }
359         
360         return out_buffer;
361 }
362
363 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
364 {
365         size_t size;
366         smb_ucs2_t *buffer;
367         
368         size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen,
369                                        (void **) &buffer);
370         if (size == -1) {
371                 smb_panic("failed to create UCS2 buffer");
372         }
373         if (!strlower_w(buffer) && (dest == src)) {
374                 free(buffer);
375                 return srclen;
376         }
377         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
378         free(buffer);
379         return size;
380 }
381
382 /**
383  strdup() a unix string to lower case.
384 **/
385
386 char *strdup_lower(const char *s)
387 {
388         size_t size;
389         smb_ucs2_t *buffer;
390         char *out_buffer;
391         
392         size = push_ucs2_allocate(&buffer, s);
393         if (size == -1) {
394                 return NULL;
395         }
396
397         strlower_w(buffer);
398         
399         size = pull_ucs2_allocate(&out_buffer, buffer);
400         SAFE_FREE(buffer);
401
402         if (size == -1) {
403                 return NULL;
404         }
405         
406         return out_buffer;
407 }
408
409 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
410 {
411         if (flags & (STR_NOALIGN|STR_ASCII))
412                 return 0;
413         return PTR_DIFF(p, base_ptr) & 1;
414 }
415
416
417 /**
418  * Copy a string from a char* unix src to a dos codepage string destination.
419  *
420  * @return the number of bytes occupied by the string in the destination.
421  *
422  * @param flags can include
423  * <dl>
424  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
425  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
426  * </dl>
427  *
428  * @param dest_len the maximum length in bytes allowed in the
429  * destination.  If @p dest_len is -1 then no maximum is used.
430  **/
431 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
432 {
433         size_t src_len = strlen(src);
434         pstring tmpbuf;
435
436         /* treat a pstring as "unlimited" length */
437         if (dest_len == (size_t)-1)
438                 dest_len = sizeof(pstring);
439
440         if (flags & STR_UPPER) {
441                 pstrcpy(tmpbuf, src);
442                 strupper_m(tmpbuf);
443                 src = tmpbuf;
444         }
445
446         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
447                 src_len++;
448
449         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
450 }
451
452 size_t push_ascii_fstring(void *dest, const char *src)
453 {
454         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
455 }
456
457 size_t push_ascii_pstring(void *dest, const char *src)
458 {
459         return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
460 }
461
462 /**
463  * Copy a string from a dos codepage source to a unix char* destination.
464  *
465  * The resulting string in "dest" is always null terminated.
466  *
467  * @param flags can have:
468  * <dl>
469  * <dt>STR_TERMINATE</dt>
470  * <dd>STR_TERMINATE means the string in @p src
471  * is null terminated, and src_len is ignored.</dd>
472  * </dl>
473  *
474  * @param src_len is the length of the source area in bytes.
475  * @returns the number of bytes occupied by the string in @p src.
476  **/
477 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
478 {
479         size_t ret;
480
481         if (dest_len == (size_t)-1)
482                 dest_len = sizeof(pstring);
483
484         if (flags & STR_TERMINATE) {
485                 if (src_len == (size_t)-1) {
486                         src_len = strlen(src) + 1;
487                 } else {
488                         size_t len = strnlen(src, src_len);
489                         if (len < src_len)
490                                 len++;
491                         src_len = len;
492                 }
493         }
494
495         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
496
497         if (dest_len)
498                 dest[MIN(ret, dest_len-1)] = 0;
499         else 
500                 dest[0] = 0;
501
502         return src_len;
503 }
504
505 size_t pull_ascii_pstring(char *dest, const void *src)
506 {
507         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
508 }
509
510 size_t pull_ascii_fstring(char *dest, const void *src)
511 {
512         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
513 }
514
515 /**
516  * Copy a string from a char* src to a unicode destination.
517  *
518  * @returns the number of bytes occupied by the string in the destination.
519  *
520  * @param flags can have:
521  *
522  * <dl>
523  * <dt>STR_TERMINATE <dd>means include the null termination.
524  * <dt>STR_UPPER     <dd>means uppercase in the destination.
525  * <dt>STR_NOALIGN   <dd>means don't do alignment.
526  * </dl>
527  *
528  * @param dest_len is the maximum length allowed in the
529  * destination. If dest_len is -1 then no maxiumum is used.
530  **/
531 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
532 {
533         size_t len=0;
534         size_t src_len = strlen(src);
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_TERMINATE)
541                 src_len++;
542
543         if (ucs2_align(base_ptr, dest, flags)) {
544                 *(char *)dest = 0;
545                 dest = (void *)((char *)dest + 1);
546                 if (dest_len) dest_len--;
547                 len++;
548         }
549
550         /* ucs2 is always a multiple of 2 bytes */
551         dest_len &= ~1;
552
553         len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
554
555         if (flags & STR_UPPER) {
556                 smb_ucs2_t *dest_ucs2 = dest;
557                 size_t i;
558                 for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
559                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
560                         if (v != dest_ucs2[i]) {
561                                 dest_ucs2[i] = v;
562                         }
563                 }
564         }
565
566         return len;
567 }
568
569
570 /**
571  * Copy a string from a unix char* src to a UCS2 destination,
572  * allocating a buffer using talloc().
573  *
574  * @param dest always set at least to NULL 
575  *
576  * @returns The number of bytes occupied by the string in the destination
577  *         or -1 in case of error.
578  **/
579 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
580 {
581         size_t src_len = strlen(src)+1;
582
583         *dest = NULL;
584         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
585 }
586
587
588 /**
589  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
590  *
591  * @param dest always set at least to NULL 
592  *
593  * @returns The number of bytes occupied by the string in the destination
594  *         or -1 in case of error.
595  **/
596
597 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
598 {
599         size_t src_len = strlen(src)+1;
600
601         *dest = NULL;
602         return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest);  
603 }
604
605 /**
606  Copy a string from a char* src to a UTF-8 destination.
607  Return the number of bytes occupied by the string in the destination
608  Flags can have:
609   STR_TERMINATE means include the null termination
610   STR_UPPER     means uppercase in the destination
611  dest_len is the maximum length allowed in the destination. If dest_len
612  is -1 then no maxiumum is used.
613 **/
614
615 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
616 {
617         size_t src_len = strlen(src);
618         pstring tmpbuf;
619
620         /* treat a pstring as "unlimited" length */
621         if (dest_len == (size_t)-1)
622                 dest_len = sizeof(pstring);
623
624         if (flags & STR_UPPER) {
625                 pstrcpy(tmpbuf, src);
626                 strupper_m(tmpbuf);
627                 src = tmpbuf;
628         }
629
630         if (flags & STR_TERMINATE)
631                 src_len++;
632
633         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
634 }
635
636 size_t push_utf8_fstring(void *dest, const char *src)
637 {
638         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
639 }
640
641 /**
642  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
643  *
644  * @param dest always set at least to NULL 
645  *
646  * @returns The number of bytes occupied by the string in the destination
647  **/
648
649 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
650 {
651         size_t src_len = strlen(src)+1;
652
653         *dest = NULL;
654         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
655 }
656
657 /**
658  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
659  *
660  * @param dest always set at least to NULL 
661  *
662  * @returns The number of bytes occupied by the string in the destination
663  **/
664
665 size_t push_utf8_allocate(char **dest, const char *src)
666 {
667         size_t src_len = strlen(src)+1;
668
669         *dest = NULL;
670         return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest);  
671 }
672
673 /**
674  Copy a string from a ucs2 source to a unix char* destination.
675  Flags can have:
676   STR_TERMINATE means the string in src is null terminated.
677   STR_NOALIGN   means don't try to align.
678  if STR_TERMINATE is set then src_len is ignored if it is -1.
679  src_len is the length of the source area in bytes
680  Return the number of bytes occupied by the string in src.
681  The resulting string in "dest" is always null terminated.
682 **/
683
684 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
685 {
686         size_t ret;
687
688         if (dest_len == (size_t)-1)
689                 dest_len = sizeof(pstring);
690
691         if (ucs2_align(base_ptr, src, flags)) {
692                 src = (const void *)((const char *)src + 1);
693                 if (src_len > 0)
694                         src_len--;
695         }
696
697         if (flags & STR_TERMINATE) {
698                 if (src_len == (size_t)-1) {
699                         src_len = strlen_w(src)*2 + 2;
700                 } else {
701                         size_t len = strnlen_w(src, src_len/2);
702                         if (len < src_len/2)
703                                 len++;
704                         src_len = len*2;
705                 }
706         }
707
708         /* ucs2 is always a multiple of 2 bytes */
709         if (src_len != (size_t)-1)
710                 src_len &= ~1;
711         
712         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
713         if (dest_len)
714                 dest[MIN(ret, dest_len-1)] = 0;
715         else 
716                 dest[0] = 0;
717
718         return src_len;
719 }
720
721 size_t pull_ucs2_pstring(char *dest, const void *src)
722 {
723         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
724 }
725
726 size_t pull_ucs2_fstring(char *dest, const void *src)
727 {
728         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
729 }
730
731 /**
732  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
733  *
734  * @param dest always set at least to NULL 
735  *
736  * @returns The number of bytes occupied by the string in the destination
737  **/
738
739 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
740 {
741         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
742         *dest = NULL;
743         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
744 }
745
746 /**
747  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
748  *
749  * @param dest always set at least to NULL 
750  *
751  * @returns The number of bytes occupied by the string in the destination
752  **/
753
754 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
755 {
756         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
757         *dest = NULL;
758         return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, (void **)dest);  
759 }
760
761 /**
762  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
763  *
764  * @param dest always set at least to NULL 
765  *
766  * @returns The number of bytes occupied by the string in the destination
767  **/
768
769 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
770 {
771         size_t src_len = strlen(src)+1;
772         *dest = NULL;
773         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);       
774 }
775
776 /**
777  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
778  *
779  * @param dest always set at least to NULL 
780  *
781  * @returns The number of bytes occupied by the string in the destination
782  **/
783
784 size_t pull_utf8_allocate(void **dest, const char *src)
785 {
786         size_t src_len = strlen(src)+1;
787         *dest = NULL;
788         return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest);   
789 }
790  
791 /**
792  Copy a string from a char* src to a unicode or ascii
793  dos codepage destination choosing unicode or ascii based on the 
794  flags in the SMB buffer starting at base_ptr.
795  Return the number of bytes occupied by the string in the destination.
796  flags can have:
797   STR_TERMINATE means include the null termination.
798   STR_UPPER     means uppercase in the destination.
799   STR_ASCII     use ascii even with unicode packet.
800   STR_NOALIGN   means don't do alignment.
801  dest_len is the maximum length allowed in the destination. If dest_len
802  is -1 then no maxiumum is used.
803 **/
804
805 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)
806 {
807 #ifdef DEVELOPER
808         /* We really need to zero fill here, not clobber
809          * region, as we want to ensure that valgrind thinks
810          * all of the outgoing buffer has been written to
811          * so a send() or write() won't trap an error.
812          * JRA.
813          */
814 #if 0
815         if (dest_len != (size_t)-1)
816                 clobber_region(function, line, dest, dest_len);
817 #else
818         if (dest_len != (size_t)-1)
819                 memset(dest, '\0', dest_len);
820 #endif
821 #endif
822
823         if (!(flags & STR_ASCII) && \
824             ((flags & STR_UNICODE || \
825               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
826                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
827         }
828         return push_ascii(dest, src, dest_len, flags);
829 }
830
831
832 /**
833  Copy a string from a unicode or ascii source (depending on
834  the packet flags) to a char* destination.
835  Flags can have:
836   STR_TERMINATE means the string in src is null terminated.
837   STR_UNICODE   means to force as unicode.
838   STR_ASCII     use ascii even with unicode packet.
839   STR_NOALIGN   means don't do alignment.
840  if STR_TERMINATE is set then src_len is ignored is it is -1
841  src_len is the length of the source area in bytes.
842  Return the number of bytes occupied by the string in src.
843  The resulting string in "dest" is always null terminated.
844 **/
845
846 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)
847 {
848         if (dest_len != (size_t)-1)
849                 clobber_region(function, line, dest, dest_len);
850
851         if (!(flags & STR_ASCII) && \
852             ((flags & STR_UNICODE || \
853               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
854                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
855         }
856         return pull_ascii(dest, src, dest_len, src_len, flags);
857 }
858
859 size_t align_string(const void *base_ptr, const char *p, int flags)
860 {
861         if (!(flags & STR_ASCII) && \
862             ((flags & STR_UNICODE || \
863               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
864                 return ucs2_align(base_ptr, p, flags);
865         }
866         return 0;
867 }
868