r5665: the data within el2->values can still be used at this point, so don't free
[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    
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 #include "system/iconv.h"
25 #include "pstring.h"
26
27 /**
28  * @file
29  *
30  * @brief Character-set conversion routines built on our iconv.
31  * 
32  * @note Samba's internal character set (at least in the 3.0 series)
33  * is always the same as the one for the Unix filesystem.  It is
34  * <b>not</b> necessarily UTF-8 and may be different on machines that
35  * need i18n filenames to be compatible with Unix software.  It does
36  * have to be a superset of ASCII.  All multibyte sequences must start
37  * with a byte with the high bit set.
38  *
39  * @sa lib/iconv.c
40  */
41
42 /**
43  * Return the name of a charset to give to iconv().
44  **/
45 static const char *charset_name(charset_t ch)
46 {
47         const char *ret = NULL;
48
49         if (ch == CH_UTF16) ret = "UTF-16LE";
50         else if (ch == CH_UNIX) ret = lp_unix_charset();
51         else if (ch == CH_DOS) ret = lp_dos_charset();
52         else if (ch == CH_DISPLAY) ret = lp_display_charset();
53         else if (ch == CH_UTF8) ret = "UTF8";
54         else if (ch == CH_UTF16BE) ret = "UTF-16BE";
55
56         if (!ret || !*ret) ret = "ASCII";
57         return ret;
58 }
59
60 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
61
62 /**
63  re-initialize iconv conversion descriptors
64 **/
65 void init_iconv(void)
66 {
67         charset_t c1, c2;
68         for (c1=0;c1<NUM_CHARSETS;c1++) {
69                 for (c2=0;c2<NUM_CHARSETS;c2++) {
70                         if (conv_handles[c1][c2] != NULL) {
71                                 if (conv_handles[c1][c2] != (smb_iconv_t)-1) {
72                                         smb_iconv_close(conv_handles[c1][c2]);
73                                 }
74                                 conv_handles[c1][c2] = NULL;
75                         }
76                 }
77         }
78
79 }
80
81 /*
82   on-demand initialisation of conversion handles
83 */
84 static smb_iconv_t get_conv_handle(charset_t from, charset_t to)
85 {
86         const char *n1, *n2;
87         static int initialised;
88         /* auto-free iconv memory on exit so valgrind reports are easier
89            to look at */
90         if (initialised == 0) {
91                 initialised = 1;
92                 
93 #ifdef LC_ALL
94                 /* we set back the locale to C to get ASCII-compatible
95                    toupper/lower functions.  For now we do not need
96                    any other POSIX localisations anyway. When we
97                    should really need localized string functions one
98                    day we need to write our own ascii_tolower etc.
99                 */
100                 setlocale(LC_ALL, "C");
101 #endif
102
103                 atexit(init_iconv);
104         }
105
106         if (conv_handles[from][to]) {
107                 return conv_handles[from][to];
108         }
109
110         n1 = charset_name(from);
111         n2 = charset_name(to);
112
113         conv_handles[from][to] = smb_iconv_open(n2,n1);
114         
115         if (conv_handles[from][to] == (smb_iconv_t)-1) {
116                 if ((from == CH_DOS || to == CH_DOS) &&
117                     strcasecmp(charset_name(CH_DOS), "ASCII") != 0) {
118                         DEBUG(0,("dos charset '%s' unavailable - using ASCII\n",
119                                  charset_name(CH_DOS)));
120                         lp_set_cmdline("dos charset", "ASCII");
121
122                         n1 = charset_name(from);
123                         n2 = charset_name(to);
124                         
125                         conv_handles[from][to] = smb_iconv_open(n2,n1);
126                 }
127         }
128
129         return conv_handles[from][to];
130 }
131
132
133 /**
134  * Convert string from one encoding to another, making error checking etc
135  *
136  * @param src pointer to source string (multibyte or singlebyte)
137  * @param srclen length of the source string in bytes
138  * @param dest pointer to destination string (multibyte or singlebyte)
139  * @param destlen maximal length allowed for string
140  * @returns the number of bytes occupied in the destination
141  **/
142 ssize_t convert_string(charset_t from, charset_t to,
143                       void const *src, size_t srclen, 
144                       void *dest, size_t destlen)
145 {
146         size_t i_len, o_len;
147         size_t retval;
148         const char* inbuf = (const char*)src;
149         char* outbuf = (char*)dest;
150         smb_iconv_t descriptor;
151
152         if (srclen == (size_t)-1)
153                 srclen = strlen(src)+1;
154
155         descriptor = get_conv_handle(from, to);
156
157         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
158                 /* conversion not supported, use as is */
159                 size_t len = MIN(srclen,destlen);
160                 memcpy(dest,src,len);
161                 return len;
162         }
163
164         i_len=srclen;
165         o_len=destlen;
166         retval = smb_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
167         if(retval==(size_t)-1) {
168                 const char *reason;
169                 switch(errno) {
170                         case EINVAL:
171                                 reason="Incomplete multibyte sequence";
172                                 break;
173                         case E2BIG:
174                                 reason="No more room"; 
175                                 if (from == CH_UNIX) {
176                                         DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d - '%s'\n",
177                                                  charset_name(from), charset_name(to),
178                                                  srclen, destlen, (const char *)src));
179                                 } else {
180                                         DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d\n",
181                                                  charset_name(from), charset_name(to),
182                                                  srclen, destlen));
183                                 }
184                                break;
185                         case EILSEQ:
186                                reason="Illegal multibyte sequence";
187                                break;
188                 }
189                 /* smb_panic(reason); */
190         }
191         return destlen-o_len;
192 }
193
194 /**
195  * Convert between character sets, allocating a new buffer using talloc for the result.
196  *
197  * @param srclen length of source buffer.
198  * @param dest always set at least to NULL
199  * @note -1 is not accepted for srclen.
200  *
201  * @returns Size in bytes of the converted string; or -1 in case of error.
202  **/
203
204 ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
205                               void const *src, size_t srclen, void **dest)
206 {
207         size_t i_len, o_len, destlen;
208         size_t retval;
209         const char *inbuf = (const char *)src;
210         char *outbuf, *ob;
211         smb_iconv_t descriptor;
212
213         *dest = NULL;
214
215         if (src == NULL || srclen == (size_t)-1 || srclen == 0)
216                 return (size_t)-1;
217
218         descriptor = get_conv_handle(from, to);
219
220         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
221                 /* conversion not supported, return -1*/
222                 DEBUG(3, ("convert_string_talloc: conversion from %s to %s not supported!\n",
223                           charset_name(from), charset_name(to)));
224                 return -1;
225         }
226
227         /* it is _very_ rare that a conversion increases the size by
228            more than 3x */
229         destlen = srclen;
230         outbuf = NULL;
231 convert:
232         destlen = 2 + (destlen*3);
233         ob = talloc_realloc(ctx, outbuf, char, destlen);
234         if (!ob) {
235                 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
236                 talloc_free(outbuf);
237                 return (size_t)-1;
238         } else {
239                 outbuf = ob;
240         }
241
242         /* we give iconv 2 less bytes to allow us to terminate at the
243            end */
244         i_len = srclen;
245         o_len = destlen-2;
246         retval = smb_iconv(descriptor,
247                            &inbuf, &i_len,
248                            &outbuf, &o_len);
249         if(retval == (size_t)-1)                {
250                 const char *reason="unknown error";
251                 switch(errno) {
252                         case EINVAL:
253                                 reason="Incomplete multibyte sequence";
254                                 break;
255                         case E2BIG:
256                                 goto convert;           
257                         case EILSEQ:
258                                 reason="Illegal multibyte sequence";
259                                 break;
260                 }
261                 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
262                 talloc_free(ob);
263                 return (size_t)-1;
264         }
265         
266         destlen = (destlen-2) - o_len;
267
268         /* guarantee null termination in all charsets */
269         SSVAL(ob, destlen, 0);
270
271         *dest = ob;
272
273         return destlen;
274 }
275
276 /**
277  * Copy a string from a char* unix src to a dos codepage string destination.
278  *
279  * @return the number of bytes occupied by the string in the destination.
280  *
281  * @param flags can include
282  * <dl>
283  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
284  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
285  * </dl>
286  *
287  * @param dest_len the maximum length in bytes allowed in the
288  * destination.  If @p dest_len is -1 then no maximum is used.
289  **/
290 ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
291 {
292         size_t src_len;
293         ssize_t ret;
294
295         if (flags & STR_UPPER) {
296                 char *tmpbuf = strupper_talloc(NULL, src);
297                 if (tmpbuf == NULL) {
298                         return -1;
299                 }
300                 ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
301                 talloc_free(tmpbuf);
302                 return ret;
303         }
304
305         /* treat a pstring as "unlimited" length */
306         if (dest_len == (size_t)-1)
307                 dest_len = sizeof(pstring);
308
309         src_len = strlen(src);
310
311         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
312                 src_len++;
313
314         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
315 }
316
317 /**
318  * Copy a string from a unix char* src to an ASCII destination,
319  * allocating a buffer using talloc().
320  *
321  * @param dest always set at least to NULL 
322  *
323  * @returns The number of bytes occupied by the string in the destination
324  *         or -1 in case of error.
325  **/
326 ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
327 {
328         size_t src_len = strlen(src)+1;
329
330         *dest = NULL;
331         return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest);
332 }
333
334
335 /**
336  * Copy a string from a dos codepage source to a unix char* destination.
337  *
338  * The resulting string in "dest" is always null terminated.
339  *
340  * @param flags can have:
341  * <dl>
342  * <dt>STR_TERMINATE</dt>
343  * <dd>STR_TERMINATE means the string in @p src
344  * is null terminated, and src_len is ignored.</dd>
345  * </dl>
346  *
347  * @param src_len is the length of the source area in bytes.
348  * @returns the number of bytes occupied by the string in @p src.
349  **/
350 ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
351 {
352         size_t ret;
353
354         if (dest_len == (size_t)-1)
355                 dest_len = sizeof(pstring);
356
357         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
358                 if (src_len == (size_t)-1) {
359                         src_len = strlen(src) + 1;
360                 } else {
361                         size_t len = strnlen(src, src_len);
362                         if (len < src_len)
363                                 len++;
364                         src_len = len;
365                 }
366         }
367
368         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
369
370         if (dest_len)
371                 dest[MIN(ret, dest_len-1)] = 0;
372
373         return src_len;
374 }
375
376 /**
377  * Copy a string from a char* src to a unicode destination.
378  *
379  * @returns the number of bytes occupied by the string in the destination.
380  *
381  * @param flags can have:
382  *
383  * <dl>
384  * <dt>STR_TERMINATE <dd>means include the null termination.
385  * <dt>STR_UPPER     <dd>means uppercase in the destination.
386  * <dt>STR_NOALIGN   <dd>means don't do alignment.
387  * </dl>
388  *
389  * @param dest_len is the maximum length allowed in the
390  * destination. If dest_len is -1 then no maxiumum is used.
391  **/
392 ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags)
393 {
394         size_t len=0;
395         size_t src_len = strlen(src);
396         size_t ret;
397
398         if (flags & STR_UPPER) {
399                 char *tmpbuf = strupper_talloc(NULL, src);
400                 if (tmpbuf == NULL) {
401                         return -1;
402                 }
403                 ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
404                 talloc_free(tmpbuf);
405                 return ret;
406         }
407
408         /* treat a pstring as "unlimited" length */
409         if (dest_len == (size_t)-1)
410                 dest_len = sizeof(pstring);
411
412         if (flags & STR_TERMINATE)
413                 src_len++;
414
415         if (ucs2_align(NULL, 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         ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len);
426         if (ret == (size_t)-1) {
427                 return 0;
428         }
429
430         len += ret;
431
432         return len;
433 }
434
435
436 /**
437  * Copy a string from a unix char* src to a UCS2 destination,
438  * allocating a buffer using talloc().
439  *
440  * @param dest always set at least to NULL 
441  *
442  * @returns The number of bytes occupied by the string in the destination
443  *         or -1 in case of error.
444  **/
445 ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
446 {
447         size_t src_len = strlen(src)+1;
448         *dest = NULL;
449         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest);
450 }
451
452
453 /**
454  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
455  *
456  * @param dest always set at least to NULL 
457  *
458  * @returns The number of bytes occupied by the string in the destination
459  **/
460
461 ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
462 {
463         size_t src_len = strlen(src)+1;
464
465         *dest = NULL;
466         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
467 }
468
469 /**
470  Copy a string from a ucs2 source to a unix char* destination.
471  Flags can have:
472   STR_TERMINATE means the string in src is null terminated.
473   STR_NOALIGN   means don't try to align.
474  if STR_TERMINATE is set then src_len is ignored if it is -1.
475  src_len is the length of the source area in bytes
476  Return the number of bytes occupied by the string in src.
477  The resulting string in "dest" is always null terminated.
478 **/
479
480 size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
481 {
482         size_t ret;
483
484         if (dest_len == (size_t)-1)
485                 dest_len = sizeof(pstring);
486
487         if (ucs2_align(NULL, src, flags)) {
488                 src = (const void *)((const char *)src + 1);
489                 if (src_len > 0)
490                         src_len--;
491         }
492
493         if (flags & STR_TERMINATE) {
494                 if (src_len == (size_t)-1) {
495                         src_len = utf16_len(src);
496                 } else {
497                         src_len = utf16_len_n(src, src_len);
498                 }
499         }
500
501         /* ucs2 is always a multiple of 2 bytes */
502         if (src_len != (size_t)-1)
503                 src_len &= ~1;
504         
505         ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len);
506         if (dest_len)
507                 dest[MIN(ret, dest_len-1)] = 0;
508
509         return src_len;
510 }
511
512 /**
513  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
514  *
515  * @param dest always set at least to NULL 
516  *
517  * @returns The number of bytes occupied by the string in the destination
518  **/
519
520 ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src)
521 {
522         size_t src_len = utf16_len(src);
523         *dest = NULL;
524         return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest);
525 }
526
527 /**
528  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
529  *
530  * @param dest always set at least to NULL 
531  *
532  * @returns The number of bytes occupied by the string in the destination
533  **/
534
535 ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
536 {
537         size_t src_len = strlen(src)+1;
538         *dest = NULL;
539         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
540 }
541
542 /**
543  Copy a string from a char* src to a unicode or ascii
544  dos codepage destination choosing unicode or ascii based on the 
545  flags in the SMB buffer starting at base_ptr.
546  Return the number of bytes occupied by the string in the destination.
547  flags can have:
548   STR_TERMINATE means include the null termination.
549   STR_UPPER     means uppercase in the destination.
550   STR_ASCII     use ascii even with unicode packet.
551   STR_NOALIGN   means don't do alignment.
552  dest_len is the maximum length allowed in the destination. If dest_len
553  is -1 then no maxiumum is used.
554 **/
555
556 ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
557 {
558         if (flags & STR_ASCII) {
559                 return push_ascii(dest, src, dest_len, flags);
560         } else if (flags & STR_UNICODE) {
561                 return push_ucs2(dest, src, dest_len, flags);
562         } else {
563                 smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set");
564                 return -1;
565         }
566 }
567
568
569 /**
570  Copy a string from a unicode or ascii source (depending on
571  the packet flags) to a char* destination.
572  Flags can have:
573   STR_TERMINATE means the string in src is null terminated.
574   STR_UNICODE   means to force as unicode.
575   STR_ASCII     use ascii even with unicode packet.
576   STR_NOALIGN   means don't do alignment.
577  if STR_TERMINATE is set then src_len is ignored is it is -1
578  src_len is the length of the source area in bytes.
579  Return the number of bytes occupied by the string in src.
580  The resulting string in "dest" is always null terminated.
581 **/
582
583 ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
584 {
585         if (flags & STR_ASCII) {
586                 return pull_ascii(dest, src, dest_len, src_len, flags);
587         } else if (flags & STR_UNICODE) {
588                 return pull_ucs2(dest, src, dest_len, src_len, flags);
589         } else {
590                 smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set");
591                 return -1;
592         }
593 }
594
595
596 /*
597   return the unicode codepoint for the next multi-byte CH_UNIX character
598   in the string
599
600   also return the number of bytes consumed (which tells the caller
601   how many bytes to skip to get to the next CH_UNIX character)
602
603   return INVALID_CODEPOINT if the next character cannot be converted
604 */
605 codepoint_t next_codepoint(const char *str, size_t *size)
606 {
607         /* it cannot occupy more than 4 bytes in UTF16 format */
608         uint8_t buf[4];
609         smb_iconv_t descriptor;
610         size_t ilen_orig;
611         size_t ilen;
612         size_t olen;
613         char *outbuf;
614
615         if ((str[0] & 0x80) == 0) {
616                 *size = 1;
617                 return (codepoint_t)str[0];
618         }
619
620         /* we assume that no multi-byte character can take
621            more than 5 bytes. This is OK as we only
622            support codepoints up to 1M */
623         ilen_orig = strnlen(str, 5);
624         ilen = ilen_orig;
625
626         descriptor = get_conv_handle(CH_UNIX, CH_UTF16);
627         if (descriptor == (smb_iconv_t)-1) {
628                 *size = 1;
629                 return INVALID_CODEPOINT;
630         }
631
632         /* this looks a little strange, but it is needed to cope
633            with codepoints above 64k */
634         olen = 2;
635         outbuf = buf;
636         smb_iconv(descriptor,  &str, &ilen, &outbuf, &olen);
637         if (olen == 2) {
638                 olen = 4;
639                 outbuf = buf;
640                 smb_iconv(descriptor,  &str, &ilen, &outbuf, &olen);
641                 if (olen == 4) {
642                         /* we didn't convert any bytes */
643                         *size = 1;
644                         return INVALID_CODEPOINT;
645                 }
646                 olen = 4 - olen;
647         } else {
648                 olen = 2 - olen;
649         }
650
651         *size = ilen_orig - ilen;
652
653         if (olen == 2) {
654                 return (codepoint_t)SVAL(buf, 0);
655         }
656         if (olen == 4) {
657                 /* decode a 4 byte UTF16 character manually */
658                 return (codepoint_t)0x10000 + 
659                         (buf[2] | ((buf[3] & 0x3)<<8) | 
660                          (buf[0]<<10) | ((buf[1] & 0x3)<<18));
661         }
662
663         /* no other length is valid */
664         return INVALID_CODEPOINT;
665 }
666
667 /*
668   push a single codepoint into a CH_UNIX string the target string must
669   be able to hold the full character, which is guaranteed if it is at
670   least 5 bytes in size. The caller may pass less than 5 bytes if they
671   are sure the character will fit (for example, you can assume that
672   uppercase/lowercase of a character will not add more than 1 byte)
673
674   return the number of bytes occupied by the CH_UNIX character, or
675   -1 on failure
676 */
677 ssize_t push_codepoint(char *str, codepoint_t c)
678 {
679         smb_iconv_t descriptor;
680         uint8_t buf[4];
681         size_t ilen, olen;
682         const char *inbuf;
683         
684         if (c < 128) {
685                 *str = c;
686                 return 1;
687         }
688
689         descriptor = get_conv_handle(CH_UTF16, CH_UNIX);
690         if (descriptor == (smb_iconv_t)-1) {
691                 return -1;
692         }
693
694         if (c < 0x10000) {
695                 ilen = 2;
696                 olen = 5;
697                 inbuf = buf;
698                 SSVAL(buf, 0, c);
699                 smb_iconv(descriptor, &inbuf, &ilen, &str, &olen);
700                 if (ilen != 0) {
701                         return -1;
702                 }
703                 return 5 - olen;
704         }
705
706         c -= 0x10000;
707
708         buf[0] = (c>>10) & 0xFF;
709         buf[1] = (c>>18) | 0xd8;
710         buf[2] = c & 0xFF;
711         buf[3] = ((c>>8) & 0x3) | 0xdc;
712
713         ilen = 4;
714         olen = 5;
715         inbuf = buf;
716
717         smb_iconv(descriptor, &inbuf, &ilen, &str, &olen);
718         if (ilen != 0) {
719                 return -1;
720         }
721         return 5 - olen;
722 }