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