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