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