Half-way though the big conversion of all nmbd access to wire elements being
[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 static BOOL conv_silent; /* Should we do a debug if the conversion fails ? */
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                 conv_silent = True;
145                 init_doschar_table();
146                 init_valid_table();
147                 conv_silent = False;
148         }
149 }
150
151 /**
152  * Convert string from one encoding to another, making error checking etc
153  *
154  * @param src pointer to source string (multibyte or singlebyte)
155  * @param srclen length of the source string in bytes
156  * @param dest pointer to destination string (multibyte or singlebyte)
157  * @param destlen maximal length allowed for string
158  * @returns the number of bytes occupied in the destination
159  *
160  * Ensure the srclen contains the terminating zero.
161  *
162  **/
163 size_t convert_string(charset_t from, charset_t to,
164                       void const *src, size_t srclen, 
165                       void *dest, size_t destlen)
166 {
167         size_t i_len, o_len;
168         size_t retval;
169         const char* inbuf = (const char*)src;
170         char* outbuf = (char*)dest;
171         smb_iconv_t descriptor;
172
173         if (srclen == (size_t)-1)
174                 srclen = strlen(src)+1;
175         if (srclen == 0)
176                 return 0;
177
178         lazy_initialize_conv();
179
180         descriptor = conv_handles[from][to];
181
182         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
183                 if (!conv_silent)
184                         DEBUG(0,("convert_string: Conversion not supported.\n"));
185                 goto use_as_is;
186         }
187
188         i_len=srclen;
189         o_len=destlen;
190         retval = smb_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
191         if(retval==(size_t)-1) {
192                 const char *reason="unknown error";
193                 switch(errno) {
194                         case EINVAL:
195                                 reason="Incomplete multibyte sequence";
196                                 if (!conv_silent)
197                                         DEBUG(3,("convert_string: Conversion error: %s(%s)\n",reason,inbuf));
198                                 goto use_as_is;
199                         case E2BIG:
200                                 reason="No more room"; 
201                                 if (!conv_silent)
202                                         DEBUG(3, ("convert_string: Required %lu, available %lu\n",
203                                                 (unsigned long)srclen, (unsigned long)destlen));
204                                 /* we are not sure we need srclen bytes,
205                                   may be more, may be less.
206                                   We only know we need more than destlen
207                                   bytes ---simo */
208                                break;
209                         case EILSEQ:
210                                 reason="Illegal multibyte sequence";
211                                 if (!conv_silent)
212                                         DEBUG(3,("convert_string: Conversion error: %s(%s)\n",reason,inbuf));
213                                 goto use_as_is;
214                         default:
215                                 if (!conv_silent)
216                                         DEBUG(0,("convert_string: Conversion error: %s(%s)\n",reason,inbuf));
217                                 break;
218                 }
219                 /* smb_panic(reason); */
220         }
221         return destlen-o_len;
222
223  use_as_is:
224
225         /* conversion not supported, use as is */
226         {
227                 size_t len = MIN(srclen,destlen);
228                 if (len)
229                         memcpy(dest,src,len);
230                 return len;
231         }
232 }
233
234 /**
235  * Convert between character sets, allocating a new buffer for the result.
236  *
237  * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
238  * @param srclen length of source buffer.
239  * @param dest always set at least to NULL
240  * @note -1 is not accepted for srclen.
241  *
242  * @returns Size in bytes of the converted string; or -1 in case of error.
243  *
244  * Ensure the srclen contains the terminating zero.
245  **/
246
247 size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
248                                void const *src, size_t srclen, void **dest)
249 {
250         size_t i_len, o_len, destlen = MAX(srclen, 512);
251         size_t retval;
252         const char *inbuf = (const char *)src;
253         char *outbuf = NULL, *ob = NULL;
254         smb_iconv_t descriptor;
255
256         *dest = NULL;
257
258         if (src == NULL || srclen == (size_t)-1)
259                 return (size_t)-1;
260         if (srclen == 0)
261                 return 0;
262
263         lazy_initialize_conv();
264
265         descriptor = conv_handles[from][to];
266
267         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
268                 if (!conv_silent)
269                         DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
270                 goto use_as_is;
271         }
272
273 convert:
274         if ((destlen*2) < destlen) {
275                 /* wrapped ! abort. */
276                 if (!conv_silent)
277                         DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
278                 if (!ctx)
279                         SAFE_FREE(outbuf);
280                 return (size_t)-1;
281         } else {
282                 destlen = destlen * 2;
283         }
284
285         if (ctx)
286                 ob = (char *)talloc_realloc(ctx, ob, destlen);
287         else
288                 ob = (char *)Realloc(ob, destlen);
289
290         if (!ob) {
291                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
292                 if (!ctx)
293                         SAFE_FREE(outbuf);
294                 return (size_t)-1;
295         } else {
296                 outbuf = ob;
297         }
298         i_len = srclen;
299         o_len = destlen;
300         retval = smb_iconv(descriptor,
301                            &inbuf, &i_len,
302                            &outbuf, &o_len);
303         if(retval == (size_t)-1)                {
304                 const char *reason="unknown error";
305                 switch(errno) {
306                         case EINVAL:
307                                 reason="Incomplete multibyte sequence";
308                                 if (!conv_silent)
309                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
310                                 goto use_as_is;
311                         case E2BIG:
312                                 goto convert;           
313                         case EILSEQ:
314                                 reason="Illegal multibyte sequence";
315                                 if (!conv_silent)
316                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
317                                 goto use_as_is;
318                 }
319                 if (!conv_silent)
320                         DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
321                 /* smb_panic(reason); */
322                 return (size_t)-1;
323         }
324         
325         destlen = destlen - o_len;
326         if (ctx)
327                 *dest = (char *)talloc_realloc(ctx,ob,destlen);
328         else
329                 *dest = (char *)Realloc(ob,destlen);
330         if (destlen && !*dest) {
331                 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
332                 if (!ctx)
333                         SAFE_FREE(ob);
334                 return (size_t)-1;
335         }
336
337         return destlen;
338
339   use_as_is:
340
341         /* conversion not supported, use as is */
342         {
343                 if (srclen && (destlen != srclen)) {
344                         destlen = srclen;
345                         if (ctx)
346                                 ob = (char *)talloc_realloc(ctx, ob, destlen);
347                         else
348                                 ob = (char *)Realloc(ob, destlen);
349                         if (!ob) {
350                                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
351                                 if (!ctx)
352                                         SAFE_FREE(outbuf);
353                                 return (size_t)-1;
354                         }
355                 }
356                 if (srclen && ob)
357                         memcpy(ob,(const char *)src,srclen);
358                 *dest = (char *)ob;
359                 return srclen;
360         }
361 }
362
363
364 /**
365  * Convert between character sets, allocating a new buffer using talloc for the result.
366  *
367  * @param srclen length of source buffer.
368  * @param dest always set at least to NULL 
369  * @note -1 is not accepted for srclen.
370  *
371  * @returns Size in bytes of the converted string; or -1 in case of error.
372  **/
373 static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
374                                 void const *src, size_t srclen, void **dest)
375 {
376         size_t dest_len;
377
378         *dest = NULL;
379         dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest);
380         if (dest_len == (size_t)-1)
381                 return (size_t)-1;
382         if (*dest == NULL)
383                 return (size_t)-1;
384         return dest_len;
385 }
386
387 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
388 {
389         size_t size;
390         smb_ucs2_t *buffer;
391         
392         size = push_ucs2_allocate(&buffer, src);
393         if (size == -1) {
394                 smb_panic("failed to create UCS2 buffer");
395         }
396         if (!strupper_w(buffer) && (dest == src)) {
397                 free(buffer);
398                 return srclen;
399         }
400         
401         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
402         free(buffer);
403         return size;
404 }
405
406 /**
407  strdup() a unix string to upper case.
408 **/
409
410 char *strdup_upper(const char *s)
411 {
412         size_t size;
413         smb_ucs2_t *buffer;
414         char *out_buffer;
415         
416         size = push_ucs2_allocate(&buffer, s);
417         if (size == -1) {
418                 return NULL;
419         }
420
421         strupper_w(buffer);
422         
423         size = pull_ucs2_allocate(&out_buffer, buffer);
424         SAFE_FREE(buffer);
425
426         if (size == -1) {
427                 return NULL;
428         }
429         
430         return out_buffer;
431 }
432
433 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
434 {
435         size_t size;
436         smb_ucs2_t *buffer;
437         
438         size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
439                                        (void **) &buffer);
440         if (size == -1) {
441                 smb_panic("failed to create UCS2 buffer");
442         }
443         if (!strlower_w(buffer) && (dest == src)) {
444                 free(buffer);
445                 return srclen;
446         }
447         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
448         free(buffer);
449         return size;
450 }
451
452 /**
453  strdup() a unix string to lower case.
454 **/
455
456 char *strdup_lower(const char *s)
457 {
458         size_t size;
459         smb_ucs2_t *buffer;
460         char *out_buffer;
461         
462         size = push_ucs2_allocate(&buffer, s);
463         if (size == -1) {
464                 return NULL;
465         }
466
467         strlower_w(buffer);
468         
469         size = pull_ucs2_allocate(&out_buffer, buffer);
470         SAFE_FREE(buffer);
471
472         if (size == -1) {
473                 return NULL;
474         }
475         
476         return out_buffer;
477 }
478
479 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
480 {
481         if (flags & (STR_NOALIGN|STR_ASCII))
482                 return 0;
483         return PTR_DIFF(p, base_ptr) & 1;
484 }
485
486
487 /**
488  * Copy a string from a char* unix src to a dos codepage string destination.
489  *
490  * @return the number of bytes occupied by the string in the destination.
491  *
492  * @param flags can include
493  * <dl>
494  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
495  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
496  * </dl>
497  *
498  * @param dest_len the maximum length in bytes allowed in the
499  * destination.  If @p dest_len is -1 then no maximum is used.
500  **/
501 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
502 {
503         size_t src_len = strlen(src);
504         pstring tmpbuf;
505
506         /* treat a pstring as "unlimited" length */
507         if (dest_len == (size_t)-1)
508                 dest_len = sizeof(pstring);
509
510         if (flags & STR_UPPER) {
511                 pstrcpy(tmpbuf, src);
512                 strupper_m(tmpbuf);
513                 src = tmpbuf;
514         }
515
516         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
517                 src_len++;
518
519         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
520 }
521
522 size_t push_ascii_fstring(void *dest, const char *src)
523 {
524         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
525 }
526
527 size_t push_ascii_pstring(void *dest, const char *src)
528 {
529         return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
530 }
531
532 size_t push_ascii_nstring(void *dest, const char *src)
533 {
534         return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE);
535 }
536
537 /**
538  * Copy a string from a dos codepage source to a unix char* destination.
539  *
540  * The resulting string in "dest" is always null terminated.
541  *
542  * @param flags can have:
543  * <dl>
544  * <dt>STR_TERMINATE</dt>
545  * <dd>STR_TERMINATE means the string in @p src
546  * is null terminated, and src_len is ignored.</dd>
547  * </dl>
548  *
549  * @param src_len is the length of the source area in bytes.
550  * @returns the number of bytes occupied by the string in @p src.
551  **/
552 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
553 {
554         size_t ret;
555
556         if (dest_len == (size_t)-1)
557                 dest_len = sizeof(pstring);
558
559         if (flags & STR_TERMINATE) {
560                 if (src_len == (size_t)-1) {
561                         src_len = strlen(src) + 1;
562                 } else {
563                         size_t len = strnlen(src, src_len);
564                         if (len < src_len)
565                                 len++;
566                         src_len = len;
567                 }
568         }
569
570         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
571
572         if (dest_len)
573                 dest[MIN(ret, dest_len-1)] = 0;
574         else 
575                 dest[0] = 0;
576
577         return src_len;
578 }
579
580 size_t pull_ascii_pstring(char *dest, const void *src)
581 {
582         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
583 }
584
585 size_t pull_ascii_fstring(char *dest, const void *src)
586 {
587         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
588 }
589
590 size_t pull_ascii_nstring(char *dest, const void *src)
591 {
592         return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE);
593 }
594
595 /**
596  * Copy a string from a char* src to a unicode destination.
597  *
598  * @returns the number of bytes occupied by the string in the destination.
599  *
600  * @param flags can have:
601  *
602  * <dl>
603  * <dt>STR_TERMINATE <dd>means include the null termination.
604  * <dt>STR_UPPER     <dd>means uppercase in the destination.
605  * <dt>STR_NOALIGN   <dd>means don't do alignment.
606  * </dl>
607  *
608  * @param dest_len is the maximum length allowed in the
609  * destination. If dest_len is -1 then no maxiumum is used.
610  **/
611 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
612 {
613         size_t len=0;
614         size_t src_len = strlen(src);
615
616         /* treat a pstring as "unlimited" length */
617         if (dest_len == (size_t)-1)
618                 dest_len = sizeof(pstring);
619
620         if (flags & STR_TERMINATE)
621                 src_len++;
622
623         if (ucs2_align(base_ptr, dest, flags)) {
624                 *(char *)dest = 0;
625                 dest = (void *)((char *)dest + 1);
626                 if (dest_len) dest_len--;
627                 len++;
628         }
629
630         /* ucs2 is always a multiple of 2 bytes */
631         dest_len &= ~1;
632
633         len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
634
635         if (flags & STR_UPPER) {
636                 smb_ucs2_t *dest_ucs2 = dest;
637                 size_t i;
638                 for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
639                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
640                         if (v != dest_ucs2[i]) {
641                                 dest_ucs2[i] = v;
642                         }
643                 }
644         }
645
646         return len;
647 }
648
649
650 /**
651  * Copy a string from a unix char* src to a UCS2 destination,
652  * allocating a buffer using talloc().
653  *
654  * @param dest always set at least to NULL 
655  *
656  * @returns The number of bytes occupied by the string in the destination
657  *         or -1 in case of error.
658  **/
659 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
660 {
661         size_t src_len = strlen(src)+1;
662
663         *dest = NULL;
664         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
665 }
666
667
668 /**
669  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
670  *
671  * @param dest always set at least to NULL 
672  *
673  * @returns The number of bytes occupied by the string in the destination
674  *         or -1 in case of error.
675  **/
676
677 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
678 {
679         size_t src_len = strlen(src)+1;
680
681         *dest = NULL;
682         return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);    
683 }
684
685 /**
686  Copy a string from a char* src to a UTF-8 destination.
687  Return the number of bytes occupied by the string in the destination
688  Flags can have:
689   STR_TERMINATE means include the null termination
690   STR_UPPER     means uppercase in the destination
691  dest_len is the maximum length allowed in the destination. If dest_len
692  is -1 then no maxiumum is used.
693 **/
694
695 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
696 {
697         size_t src_len = strlen(src);
698         pstring tmpbuf;
699
700         /* treat a pstring as "unlimited" length */
701         if (dest_len == (size_t)-1)
702                 dest_len = sizeof(pstring);
703
704         if (flags & STR_UPPER) {
705                 pstrcpy(tmpbuf, src);
706                 strupper_m(tmpbuf);
707                 src = tmpbuf;
708         }
709
710         if (flags & STR_TERMINATE)
711                 src_len++;
712
713         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
714 }
715
716 size_t push_utf8_fstring(void *dest, const char *src)
717 {
718         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
719 }
720
721 /**
722  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
723  *
724  * @param dest always set at least to NULL 
725  *
726  * @returns The number of bytes occupied by the string in the destination
727  **/
728
729 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
730 {
731         size_t src_len = strlen(src)+1;
732
733         *dest = NULL;
734         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
735 }
736
737 /**
738  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
739  *
740  * @param dest always set at least to NULL 
741  *
742  * @returns The number of bytes occupied by the string in the destination
743  **/
744
745 size_t push_utf8_allocate(char **dest, const char *src)
746 {
747         size_t src_len = strlen(src)+1;
748
749         *dest = NULL;
750         return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);    
751 }
752
753 /**
754  Copy a string from a ucs2 source to a unix char* destination.
755  Flags can have:
756   STR_TERMINATE means the string in src is null terminated.
757   STR_NOALIGN   means don't try to align.
758  if STR_TERMINATE is set then src_len is ignored if it is -1.
759  src_len is the length of the source area in bytes
760  Return the number of bytes occupied by the string in src.
761  The resulting string in "dest" is always null terminated.
762 **/
763
764 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
765 {
766         size_t ret;
767
768         if (dest_len == (size_t)-1)
769                 dest_len = sizeof(pstring);
770
771         if (ucs2_align(base_ptr, src, flags)) {
772                 src = (const void *)((const char *)src + 1);
773                 if (src_len > 0)
774                         src_len--;
775         }
776
777         if (flags & STR_TERMINATE) {
778                 if (src_len == (size_t)-1) {
779                         src_len = strlen_w(src)*2 + 2;
780                 } else {
781                         size_t len = strnlen_w(src, src_len/2);
782                         if (len < src_len/2)
783                                 len++;
784                         src_len = len*2;
785                 }
786         }
787
788         /* ucs2 is always a multiple of 2 bytes */
789         if (src_len != (size_t)-1)
790                 src_len &= ~1;
791         
792         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
793         if (dest_len)
794                 dest[MIN(ret, dest_len-1)] = 0;
795         else 
796                 dest[0] = 0;
797
798         return src_len;
799 }
800
801 size_t pull_ucs2_pstring(char *dest, const void *src)
802 {
803         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
804 }
805
806 size_t pull_ucs2_fstring(char *dest, const void *src)
807 {
808         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
809 }
810
811 /**
812  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
813  *
814  * @param dest always set at least to NULL 
815  *
816  * @returns The number of bytes occupied by the string in the destination
817  **/
818
819 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
820 {
821         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
822         *dest = NULL;
823         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
824 }
825
826 /**
827  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
828  *
829  * @param dest always set at least to NULL 
830  *
831  * @returns The number of bytes occupied by the string in the destination
832  **/
833
834 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
835 {
836         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
837         *dest = NULL;
838         return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);    
839 }
840
841 /**
842  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
843  *
844  * @param dest always set at least to NULL 
845  *
846  * @returns The number of bytes occupied by the string in the destination
847  **/
848
849 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
850 {
851         size_t src_len = strlen(src)+1;
852         *dest = NULL;
853         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);       
854 }
855
856 /**
857  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
858  *
859  * @param dest always set at least to NULL 
860  *
861  * @returns The number of bytes occupied by the string in the destination
862  **/
863
864 size_t pull_utf8_allocate(void **dest, const char *src)
865 {
866         size_t src_len = strlen(src)+1;
867         *dest = NULL;
868         return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, dest);     
869 }
870  
871 /**
872  Copy a string from a char* src to a unicode or ascii
873  dos codepage destination choosing unicode or ascii based on the 
874  flags in the SMB buffer starting at base_ptr.
875  Return the number of bytes occupied by the string in the destination.
876  flags can have:
877   STR_TERMINATE means include the null termination.
878   STR_UPPER     means uppercase in the destination.
879   STR_ASCII     use ascii even with unicode packet.
880   STR_NOALIGN   means don't do alignment.
881  dest_len is the maximum length allowed in the destination. If dest_len
882  is -1 then no maxiumum is used.
883 **/
884
885 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)
886 {
887 #ifdef DEVELOPER
888         /* We really need to zero fill here, not clobber
889          * region, as we want to ensure that valgrind thinks
890          * all of the outgoing buffer has been written to
891          * so a send() or write() won't trap an error.
892          * JRA.
893          */
894 #if 0
895         if (dest_len != (size_t)-1)
896                 clobber_region(function, line, dest, dest_len);
897 #else
898         if (dest_len != (size_t)-1)
899                 memset(dest, '\0', dest_len);
900 #endif
901 #endif
902
903         if (!(flags & STR_ASCII) && \
904             ((flags & STR_UNICODE || \
905               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
906                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
907         }
908         return push_ascii(dest, src, dest_len, flags);
909 }
910
911
912 /**
913  Copy a string from a unicode or ascii source (depending on
914  the packet flags) to a char* destination.
915  Flags can have:
916   STR_TERMINATE means the string in src is null terminated.
917   STR_UNICODE   means to force as unicode.
918   STR_ASCII     use ascii even with unicode packet.
919   STR_NOALIGN   means don't do alignment.
920  if STR_TERMINATE is set then src_len is ignored is it is -1
921  src_len is the length of the source area in bytes.
922  Return the number of bytes occupied by the string in src.
923  The resulting string in "dest" is always null terminated.
924 **/
925
926 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)
927 {
928         if (dest_len != (size_t)-1)
929                 clobber_region(function, line, dest, dest_len);
930
931         if (!(flags & STR_ASCII) && \
932             ((flags & STR_UNICODE || \
933               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
934                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
935         }
936         return pull_ascii(dest, src, dest_len, src_len, flags);
937 }
938
939 size_t align_string(const void *base_ptr, const char *p, int flags)
940 {
941         if (!(flags & STR_ASCII) && \
942             ((flags & STR_UNICODE || \
943               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
944                 return ucs2_align(base_ptr, p, flags);
945         }
946         return 0;
947 }
948