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