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