r8667: Further simply the provision script, by removing the 'name' attribute.
[kai/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                                                  (int)srclen, (int)destlen, 
179                                                  (const char *)src));
180                                 } else {
181                                         DEBUG(0,("E2BIG: convert_string(%s,%s): srclen=%d destlen=%d\n",
182                                                  charset_name(from), charset_name(to),
183                                                  (int)srclen, (int)destlen));
184                                 }
185                                break;
186                         case EILSEQ:
187                                reason="Illegal multibyte sequence";
188                                break;
189                 }
190                 /* smb_panic(reason); */
191         }
192         return destlen-o_len;
193 }
194
195 /**
196  * Convert between character sets, allocating a new buffer using talloc for the result.
197  *
198  * @param srclen length of source buffer.
199  * @param dest always set at least to NULL
200  * @note -1 is not accepted for srclen.
201  *
202  * @returns Size in bytes of the converted string; or -1 in case of error.
203  **/
204
205 ssize_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
206                               void const *src, size_t srclen, void **dest)
207 {
208         size_t i_len, o_len, destlen;
209         size_t retval;
210         const char *inbuf = (const char *)src;
211         char *outbuf, *ob;
212         smb_iconv_t descriptor;
213
214         *dest = NULL;
215
216         if (src == NULL || srclen == (size_t)-1 || srclen == 0)
217                 return (size_t)-1;
218
219         descriptor = get_conv_handle(from, to);
220
221         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
222                 /* conversion not supported, return -1*/
223                 DEBUG(3, ("convert_string_talloc: conversion from %s to %s not supported!\n",
224                           charset_name(from), charset_name(to)));
225                 return -1;
226         }
227
228         /* it is _very_ rare that a conversion increases the size by
229            more than 3x */
230         destlen = srclen;
231         outbuf = NULL;
232 convert:
233         destlen = 2 + (destlen*3);
234         ob = talloc_realloc(ctx, outbuf, char, destlen);
235         if (!ob) {
236                 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
237                 talloc_free(outbuf);
238                 return (size_t)-1;
239         } else {
240                 outbuf = ob;
241         }
242
243         /* we give iconv 2 less bytes to allow us to terminate at the
244            end */
245         i_len = srclen;
246         o_len = destlen-2;
247         retval = smb_iconv(descriptor,
248                            &inbuf, &i_len,
249                            &outbuf, &o_len);
250         if(retval == (size_t)-1)                {
251                 const char *reason="unknown error";
252                 switch(errno) {
253                         case EINVAL:
254                                 reason="Incomplete multibyte sequence";
255                                 break;
256                         case E2BIG:
257                                 goto convert;           
258                         case EILSEQ:
259                                 reason="Illegal multibyte sequence";
260                                 break;
261                 }
262                 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
263                 talloc_free(ob);
264                 return (size_t)-1;
265         }
266         
267         destlen = (destlen-2) - o_len;
268
269         /* guarantee null termination in all charsets */
270         SSVAL(ob, destlen, 0);
271
272         *dest = ob;
273
274         return destlen;
275 }
276
277 /**
278  * Copy a string from a char* unix src to a dos codepage string destination.
279  *
280  * @return the number of bytes occupied by the string in the destination.
281  *
282  * @param flags can include
283  * <dl>
284  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
285  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
286  * </dl>
287  *
288  * @param dest_len the maximum length in bytes allowed in the
289  * destination.  If @p dest_len is -1 then no maximum is used.
290  **/
291 ssize_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
292 {
293         size_t src_len;
294         ssize_t ret;
295
296         if (flags & STR_UPPER) {
297                 char *tmpbuf = strupper_talloc(NULL, src);
298                 if (tmpbuf == NULL) {
299                         return -1;
300                 }
301                 ret = push_ascii(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
302                 talloc_free(tmpbuf);
303                 return ret;
304         }
305
306         /* treat a pstring as "unlimited" length */
307         if (dest_len == (size_t)-1)
308                 dest_len = sizeof(pstring);
309
310         src_len = strlen(src);
311
312         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
313                 src_len++;
314
315         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
316 }
317
318 /**
319  * Copy a string from a unix char* src to an ASCII destination,
320  * allocating a buffer using talloc().
321  *
322  * @param dest always set at least to NULL 
323  *
324  * @returns The number of bytes occupied by the string in the destination
325  *         or -1 in case of error.
326  **/
327 ssize_t push_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
328 {
329         size_t src_len = strlen(src)+1;
330
331         *dest = NULL;
332         return convert_string_talloc(ctx, CH_UNIX, CH_DOS, src, src_len, (void **)dest);
333 }
334
335
336 /**
337  * Copy a string from a dos codepage source to a unix char* destination.
338  *
339  * The resulting string in "dest" is always null terminated.
340  *
341  * @param flags can have:
342  * <dl>
343  * <dt>STR_TERMINATE</dt>
344  * <dd>STR_TERMINATE means the string in @p src
345  * is null terminated, and src_len is ignored.</dd>
346  * </dl>
347  *
348  * @param src_len is the length of the source area in bytes.
349  * @returns the number of bytes occupied by the string in @p src.
350  **/
351 ssize_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
352 {
353         size_t ret;
354
355         if (dest_len == (size_t)-1)
356                 dest_len = sizeof(pstring);
357
358         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
359                 if (src_len == (size_t)-1) {
360                         src_len = strlen(src) + 1;
361                 } else {
362                         size_t len = strnlen(src, src_len);
363                         if (len < src_len)
364                                 len++;
365                         src_len = len;
366                 }
367         }
368
369         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
370
371         if (dest_len)
372                 dest[MIN(ret, dest_len-1)] = 0;
373
374         return src_len;
375 }
376
377 /**
378  * Copy a string from a char* src to a unicode destination.
379  *
380  * @returns the number of bytes occupied by the string in the destination.
381  *
382  * @param flags can have:
383  *
384  * <dl>
385  * <dt>STR_TERMINATE <dd>means include the null termination.
386  * <dt>STR_UPPER     <dd>means uppercase in the destination.
387  * <dt>STR_NOALIGN   <dd>means don't do alignment.
388  * </dl>
389  *
390  * @param dest_len is the maximum length allowed in the
391  * destination. If dest_len is -1 then no maxiumum is used.
392  **/
393 ssize_t push_ucs2(void *dest, const char *src, size_t dest_len, int flags)
394 {
395         size_t len=0;
396         size_t src_len = strlen(src);
397         size_t ret;
398
399         if (flags & STR_UPPER) {
400                 char *tmpbuf = strupper_talloc(NULL, src);
401                 if (tmpbuf == NULL) {
402                         return -1;
403                 }
404                 ret = push_ucs2(dest, tmpbuf, dest_len, flags & ~STR_UPPER);
405                 talloc_free(tmpbuf);
406                 return ret;
407         }
408
409         /* treat a pstring as "unlimited" length */
410         if (dest_len == (size_t)-1)
411                 dest_len = sizeof(pstring);
412
413         if (flags & STR_TERMINATE)
414                 src_len++;
415
416         if (ucs2_align(NULL, dest, flags)) {
417                 *(char *)dest = 0;
418                 dest = (void *)((char *)dest + 1);
419                 if (dest_len) dest_len--;
420                 len++;
421         }
422
423         /* ucs2 is always a multiple of 2 bytes */
424         dest_len &= ~1;
425
426         ret = convert_string(CH_UNIX, CH_UTF16, src, src_len, dest, dest_len);
427         if (ret == (size_t)-1) {
428                 return 0;
429         }
430
431         len += ret;
432
433         return len;
434 }
435
436
437 /**
438  * Copy a string from a unix char* src to a UCS2 destination,
439  * allocating a buffer using talloc().
440  *
441  * @param dest always set at least to NULL 
442  *
443  * @returns The number of bytes occupied by the string in the destination
444  *         or -1 in case of error.
445  **/
446 ssize_t push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
447 {
448         size_t src_len = strlen(src)+1;
449         *dest = NULL;
450         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16, src, src_len, dest);
451 }
452
453
454 /**
455  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
456  *
457  * @param dest always set at least to NULL 
458  *
459  * @returns The number of bytes occupied by the string in the destination
460  **/
461
462 ssize_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
463 {
464         size_t src_len = strlen(src)+1;
465
466         *dest = NULL;
467         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
468 }
469
470 /**
471  Copy a string from a ucs2 source to a unix char* destination.
472  Flags can have:
473   STR_TERMINATE means the string in src is null terminated.
474   STR_NOALIGN   means don't try to align.
475  if STR_TERMINATE is set then src_len is ignored if it is -1.
476  src_len is the length of the source area in bytes
477  Return the number of bytes occupied by the string in src.
478  The resulting string in "dest" is always null terminated.
479 **/
480
481 size_t pull_ucs2(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
482 {
483         size_t ret;
484
485         if (dest_len == (size_t)-1)
486                 dest_len = sizeof(pstring);
487
488         if (ucs2_align(NULL, src, flags)) {
489                 src = (const void *)((const char *)src + 1);
490                 if (src_len > 0)
491                         src_len--;
492         }
493
494         if (flags & STR_TERMINATE) {
495                 if (src_len == (size_t)-1) {
496                         src_len = utf16_len(src);
497                 } else {
498                         src_len = utf16_len_n(src, src_len);
499                 }
500         }
501
502         /* ucs2 is always a multiple of 2 bytes */
503         if (src_len != (size_t)-1)
504                 src_len &= ~1;
505         
506         ret = convert_string(CH_UTF16, CH_UNIX, src, src_len, dest, dest_len);
507         if (dest_len)
508                 dest[MIN(ret, dest_len-1)] = 0;
509
510         return src_len;
511 }
512
513 /**
514  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
515  *
516  * @param dest always set at least to NULL 
517  *
518  * @returns The number of bytes occupied by the string in the destination
519  **/
520
521 ssize_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const void *src)
522 {
523         size_t src_len = utf16_len(src);
524         *dest = NULL;
525         return convert_string_talloc(ctx, CH_UTF16, CH_UNIX, src, src_len, (void **)dest);
526 }
527
528 /**
529  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
530  *
531  * @param dest always set at least to NULL 
532  *
533  * @returns The number of bytes occupied by the string in the destination
534  **/
535
536 ssize_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
537 {
538         size_t src_len = strlen(src)+1;
539         *dest = NULL;
540         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
541 }
542
543 /**
544  Copy a string from a char* src to a unicode or ascii
545  dos codepage destination choosing unicode or ascii based on the 
546  flags in the SMB buffer starting at base_ptr.
547  Return the number of bytes occupied by the string in the destination.
548  flags can have:
549   STR_TERMINATE means include the null termination.
550   STR_UPPER     means uppercase in the destination.
551   STR_ASCII     use ascii even with unicode packet.
552   STR_NOALIGN   means don't do alignment.
553  dest_len is the maximum length allowed in the destination. If dest_len
554  is -1 then no maxiumum is used.
555 **/
556
557 ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
558 {
559         if (flags & STR_ASCII) {
560                 return push_ascii(dest, src, dest_len, flags);
561         } else if (flags & STR_UNICODE) {
562                 return push_ucs2(dest, src, dest_len, flags);
563         } else {
564                 smb_panic("push_string requires either STR_ASCII or STR_UNICODE flag to be set");
565                 return -1;
566         }
567 }
568
569
570 /**
571  Copy a string from a unicode or ascii source (depending on
572  the packet flags) to a char* destination.
573  Flags can have:
574   STR_TERMINATE means the string in src is null terminated.
575   STR_UNICODE   means to force as unicode.
576   STR_ASCII     use ascii even with unicode packet.
577   STR_NOALIGN   means don't do alignment.
578  if STR_TERMINATE is set then src_len is ignored is it is -1
579  src_len is the length of the source area in bytes.
580  Return the number of bytes occupied by the string in src.
581  The resulting string in "dest" is always null terminated.
582 **/
583
584 ssize_t pull_string(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
585 {
586         if (flags & STR_ASCII) {
587                 return pull_ascii(dest, src, dest_len, src_len, flags);
588         } else if (flags & STR_UNICODE) {
589                 return pull_ucs2(dest, src, dest_len, src_len, flags);
590         } else {
591                 smb_panic("pull_string requires either STR_ASCII or STR_UNICODE flag to be set");
592                 return -1;
593         }
594 }
595
596
597 /*
598   return the unicode codepoint for the next multi-byte CH_UNIX character
599   in the string
600
601   also return the number of bytes consumed (which tells the caller
602   how many bytes to skip to get to the next CH_UNIX character)
603
604   return INVALID_CODEPOINT if the next character cannot be converted
605 */
606 codepoint_t next_codepoint(const char *str, size_t *size)
607 {
608         /* it cannot occupy more than 4 bytes in UTF16 format */
609         uint8_t buf[4];
610         smb_iconv_t descriptor;
611         size_t ilen_orig;
612         size_t ilen;
613         size_t olen;
614         char *outbuf;
615
616         if ((str[0] & 0x80) == 0) {
617                 *size = 1;
618                 return (codepoint_t)str[0];
619         }
620
621         /* we assume that no multi-byte character can take
622            more than 5 bytes. This is OK as we only
623            support codepoints up to 1M */
624         ilen_orig = strnlen(str, 5);
625         ilen = ilen_orig;
626
627         descriptor = get_conv_handle(CH_UNIX, CH_UTF16);
628         if (descriptor == (smb_iconv_t)-1) {
629                 *size = 1;
630                 return INVALID_CODEPOINT;
631         }
632
633         /* this looks a little strange, but it is needed to cope
634            with codepoints above 64k */
635         olen = 2;
636         outbuf = buf;
637         smb_iconv(descriptor,  &str, &ilen, &outbuf, &olen);
638         if (olen == 2) {
639                 olen = 4;
640                 outbuf = buf;
641                 smb_iconv(descriptor,  &str, &ilen, &outbuf, &olen);
642                 if (olen == 4) {
643                         /* we didn't convert any bytes */
644                         *size = 1;
645                         return INVALID_CODEPOINT;
646                 }
647                 olen = 4 - olen;
648         } else {
649                 olen = 2 - olen;
650         }
651
652         *size = ilen_orig - ilen;
653
654         if (olen == 2) {
655                 return (codepoint_t)SVAL(buf, 0);
656         }
657         if (olen == 4) {
658                 /* decode a 4 byte UTF16 character manually */
659                 return (codepoint_t)0x10000 + 
660                         (buf[2] | ((buf[3] & 0x3)<<8) | 
661                          (buf[0]<<10) | ((buf[1] & 0x3)<<18));
662         }
663
664         /* no other length is valid */
665         return INVALID_CODEPOINT;
666 }
667
668 /*
669   push a single codepoint into a CH_UNIX string the target string must
670   be able to hold the full character, which is guaranteed if it is at
671   least 5 bytes in size. The caller may pass less than 5 bytes if they
672   are sure the character will fit (for example, you can assume that
673   uppercase/lowercase of a character will not add more than 1 byte)
674
675   return the number of bytes occupied by the CH_UNIX character, or
676   -1 on failure
677 */
678 ssize_t push_codepoint(char *str, codepoint_t c)
679 {
680         smb_iconv_t descriptor;
681         uint8_t buf[4];
682         size_t ilen, olen;
683         const char *inbuf;
684         
685         if (c < 128) {
686                 *str = c;
687                 return 1;
688         }
689
690         descriptor = get_conv_handle(CH_UTF16, CH_UNIX);
691         if (descriptor == (smb_iconv_t)-1) {
692                 return -1;
693         }
694
695         if (c < 0x10000) {
696                 ilen = 2;
697                 olen = 5;
698                 inbuf = buf;
699                 SSVAL(buf, 0, c);
700                 smb_iconv(descriptor, &inbuf, &ilen, &str, &olen);
701                 if (ilen != 0) {
702                         return -1;
703                 }
704                 return 5 - olen;
705         }
706
707         c -= 0x10000;
708
709         buf[0] = (c>>10) & 0xFF;
710         buf[1] = (c>>18) | 0xd8;
711         buf[2] = c & 0xFF;
712         buf[3] = ((c>>8) & 0x3) | 0xdc;
713
714         ilen = 4;
715         olen = 5;
716         inbuf = buf;
717
718         smb_iconv(descriptor, &inbuf, &ilen, &str, &olen);
719         if (ilen != 0) {
720                 return -1;
721         }
722         return 5 - olen;
723 }