4fbad0f3d18aca24cd6227182b39f307a448b670
[vlendec/samba-autobuild/.git] / source3 / lib / charcnv.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Character set conversion Extensions
4    Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5    Copyright (C) Andrew Tridgell 2001
6    Copyright (C) Simo Sorce 2001
7    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 /* We can parameterize this if someone complains.... JRA. */
27
28 char lp_failed_convert_char(void)
29 {
30         return '_';
31 }
32
33 /**
34  * @file
35  *
36  * @brief Character-set conversion routines built on our iconv.
37  * 
38  * @note Samba's internal character set (at least in the 3.0 series)
39  * is always the same as the one for the Unix filesystem.  It is
40  * <b>not</b> necessarily UTF-8 and may be different on machines that
41  * need i18n filenames to be compatible with Unix software.  It does
42  * have to be a superset of ASCII.  All multibyte sequences must start
43  * with a byte with the high bit set.
44  *
45  * @sa lib/iconv.c
46  */
47
48
49 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
50 static BOOL conv_silent; /* Should we do a debug if the conversion fails ? */
51
52 /**
53  * Return the name of a charset to give to iconv().
54  **/
55 static const char *charset_name(charset_t ch)
56 {
57         const char *ret = NULL;
58
59         if (ch == CH_UCS2) ret = "UTF-16LE";
60         else if (ch == CH_UNIX) ret = lp_unix_charset();
61         else if (ch == CH_DOS) ret = lp_dos_charset();
62         else if (ch == CH_DISPLAY) ret = lp_display_charset();
63         else if (ch == CH_UTF8) ret = "UTF8";
64
65 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
66         if (ret && !strcmp(ret, "LOCALE")) {
67                 const char *ln = NULL;
68
69 #ifdef HAVE_SETLOCALE
70                 setlocale(LC_ALL, "");
71 #endif
72                 ln = nl_langinfo(CODESET);
73                 if (ln) {
74                         /* Check whether the charset name is supported
75                            by iconv */
76                         smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE");
77                         if (handle == (smb_iconv_t) -1) {
78                                 DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln));
79                                 ln = NULL;
80                         } else {
81                                 DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln));
82                                 smb_iconv_close(handle);
83                         }
84                 }
85                 ret = ln;
86         }
87 #ifdef HAVE_SETLOCALE
88         /* We set back the locale to C to get ASCII-compatible toupper/lower functions.
89            For now we do not need any other POSIX localisations anyway. When we should
90            really need localized string functions one day we need to write our own
91            ascii_tolower etc.
92         */
93         setlocale(LC_ALL, "C");
94  #endif
95
96 #endif
97
98         if (!ret || !*ret) ret = "ASCII";
99         return ret;
100 }
101
102 void lazy_initialize_conv(void)
103 {
104         static int initialized = False;
105
106         if (!initialized) {
107                 initialized = True;
108                 load_case_tables();
109                 init_iconv();
110         }
111 }
112
113 /**
114  * Initialize iconv conversion descriptors.
115  *
116  * This is called the first time it is needed, and also called again
117  * every time the configuration is reloaded, because the charset or
118  * codepage might have changed.
119  **/
120 void init_iconv(void)
121 {
122         int c1, c2;
123         BOOL did_reload = False;
124
125         /* so that charset_name() works we need to get the UNIX<->UCS2 going
126            first */
127         if (!conv_handles[CH_UNIX][CH_UCS2])
128                 conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), "ASCII");
129
130         if (!conv_handles[CH_UCS2][CH_UNIX])
131                 conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UCS2));
132
133         for (c1=0;c1<NUM_CHARSETS;c1++) {
134                 for (c2=0;c2<NUM_CHARSETS;c2++) {
135                         const char *n1 = charset_name((charset_t)c1);
136                         const char *n2 = charset_name((charset_t)c2);
137                         if (conv_handles[c1][c2] &&
138                             strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
139                             strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
140                                 continue;
141
142                         did_reload = True;
143
144                         if (conv_handles[c1][c2])
145                                 smb_iconv_close(conv_handles[c1][c2]);
146
147                         conv_handles[c1][c2] = smb_iconv_open(n2,n1);
148                         if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
149                                 DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
150                                          charset_name((charset_t)c1), charset_name((charset_t)c2)));
151                                 if (c1 != CH_UCS2) {
152                                         n1 = "ASCII";
153                                 }
154                                 if (c2 != CH_UCS2) {
155                                         n2 = "ASCII";
156                                 }
157                                 DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
158                                         n1, n2 ));
159                                 conv_handles[c1][c2] = smb_iconv_open(n2,n1);
160                                 if (!conv_handles[c1][c2]) {
161                                         DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1, n2));
162                                         smb_panic("init_iconv: conv_handle initialization failed.");
163                                 }
164                         }
165                 }
166         }
167
168         if (did_reload) {
169                 /* XXX: Does this really get called every time the dos
170                  * codepage changes? */
171                 /* XXX: Is the did_reload test too strict? */
172                 conv_silent = True;
173                 init_doschar_table();
174                 init_valid_table();
175                 conv_silent = False;
176         }
177 }
178
179 /**
180  * Convert string from one encoding to another, making error checking etc
181  * Slow path version - uses (slow) iconv.
182  *
183  * @param src pointer to source string (multibyte or singlebyte)
184  * @param srclen length of the source string in bytes
185  * @param dest pointer to destination string (multibyte or singlebyte)
186  * @param destlen maximal length allowed for string
187  * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
188  * @returns the number of bytes occupied in the destination
189  *
190  * Ensure the srclen contains the terminating zero.
191  *
192  **/
193
194 static size_t convert_string_internal(charset_t from, charset_t to,
195                       void const *src, size_t srclen, 
196                       void *dest, size_t destlen, BOOL allow_bad_conv)
197 {
198         size_t i_len, o_len;
199         size_t retval;
200         const char* inbuf = (const char*)src;
201         char* outbuf = (char*)dest;
202         smb_iconv_t descriptor;
203
204         lazy_initialize_conv();
205
206         descriptor = conv_handles[from][to];
207
208         if (srclen == (size_t)-1) {
209                 if (from == CH_UCS2) {
210                         srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
211                 } else {
212                         srclen = strlen((const char *)src)+1;
213                 }
214         }
215
216
217         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
218                 if (!conv_silent)
219                         DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
220                 return (size_t)-1;
221         }
222
223         i_len=srclen;
224         o_len=destlen;
225
226  again:
227
228         retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
229         if(retval==(size_t)-1) {
230                 const char *reason="unknown error";
231                 switch(errno) {
232                         case EINVAL:
233                                 reason="Incomplete multibyte sequence";
234                                 if (!conv_silent)
235                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
236                                 if (allow_bad_conv)
237                                         goto use_as_is;
238                                 break;
239                         case E2BIG:
240                                 reason="No more room"; 
241                                 if (!conv_silent) {
242                                         if (from == CH_UNIX) {
243                                                 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
244                                                         charset_name(from), charset_name(to),
245                                                         (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
246                                         } else {
247                                                 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
248                                                         charset_name(from), charset_name(to),
249                                                         (unsigned int)srclen, (unsigned int)destlen));
250                                         }
251                                 }
252                                 break;
253                         case EILSEQ:
254                                 reason="Illegal multibyte sequence";
255                                 if (!conv_silent)
256                                         DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
257                                 if (allow_bad_conv)
258                                         goto use_as_is;
259                                 break;
260                         default:
261                                 if (!conv_silent)
262                                         DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
263                                 break;
264                 }
265                 /* smb_panic(reason); */
266         }
267         return destlen-o_len;
268
269  use_as_is:
270
271         /* 
272          * Conversion not supported. This is actually an error, but there are so
273          * many misconfigured iconv systems and smb.conf's out there we can't just
274          * fail. Do a very bad conversion instead.... JRA.
275          */
276
277         {
278                 if (o_len == 0 || i_len == 0)
279                         return destlen - o_len;
280
281                 if (from == CH_UCS2 && to != CH_UCS2) {
282                         /* Can't convert from ucs2 to multibyte. Replace with the default fail char. */
283                         if (i_len < 2)
284                                 return destlen - o_len;
285                         if (i_len >= 2) {
286                                 *outbuf = lp_failed_convert_char();
287
288                                 outbuf++;
289                                 o_len--;
290
291                                 inbuf += 2;
292                                 i_len -= 2;
293                         }
294
295                         if (o_len == 0 || i_len == 0)
296                                 return destlen - o_len;
297
298                         /* Keep trying with the next char... */
299                         goto again;
300
301                 } else if (from != CH_UCS2 && to == CH_UCS2) {
302                         /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */
303                         if (o_len < 2)
304                                 return destlen - o_len;
305
306                         outbuf[0] = lp_failed_convert_char();
307                         outbuf[1] = '\0';
308
309                         inbuf++;
310                         i_len--;
311
312                         outbuf += 2;
313                         o_len -= 2;
314
315                         if (o_len == 0 || i_len == 0)
316                                 return destlen - o_len;
317
318                         /* Keep trying with the next char... */
319                         goto again;
320
321                 } else if (from != CH_UCS2 && to != CH_UCS2) {
322                         /* Failed multibyte to multibyte. Just copy the default fail char and
323                                 try again. */
324                         outbuf[0] = lp_failed_convert_char();
325
326                         inbuf++;
327                         i_len--;
328
329                         outbuf++;
330                         o_len--;
331
332                         if (o_len == 0 || i_len == 0)
333                                 return destlen - o_len;
334
335                         /* Keep trying with the next char... */
336                         goto again;
337
338                 } else {
339                         /* Keep compiler happy.... */
340                         return destlen - o_len;
341                 }
342         }
343 }
344
345 /**
346  * Convert string from one encoding to another, making error checking etc
347  * Fast path version - handles ASCII first.
348  *
349  * @param src pointer to source string (multibyte or singlebyte)
350  * @param srclen length of the source string in bytes, or -1 for nul terminated.
351  * @param dest pointer to destination string (multibyte or singlebyte)
352  * @param destlen maximal length allowed for string - *NEVER* -1.
353  * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
354  * @returns the number of bytes occupied in the destination
355  *
356  * Ensure the srclen contains the terminating zero.
357  *
358  * This function has been hand-tuned to provide a fast path.
359  * Don't change unless you really know what you are doing. JRA.
360  **/
361
362 size_t convert_string(charset_t from, charset_t to,
363                       void const *src, size_t srclen, 
364                       void *dest, size_t destlen, BOOL allow_bad_conv)
365 {
366         /*
367          * NB. We deliberately don't do a strlen here if srclen == -1.
368          * This is very expensive over millions of calls and is taken
369          * care of in the slow path in convert_string_internal. JRA.
370          */
371
372 #ifdef DEVELOPER
373         SMB_ASSERT(destlen != (size_t)-1);
374 #endif
375
376         if (srclen == 0)
377                 return 0;
378
379         if (from != CH_UCS2 && to != CH_UCS2) {
380                 const unsigned char *p = (const unsigned char *)src;
381                 unsigned char *q = (unsigned char *)dest;
382                 size_t slen = srclen;
383                 size_t dlen = destlen;
384                 unsigned char lastp = '\0';
385                 size_t retval = 0;
386
387                 /* If all characters are ascii, fast path here. */
388                 while (slen && dlen) {
389                         if ((lastp = *p) <= 0x7f) {
390                                 *q++ = *p++;
391                                 if (slen != (size_t)-1) {
392                                         slen--;
393                                 }
394                                 dlen--;
395                                 retval++;
396                                 if (!lastp)
397                                         break;
398                         } else {
399 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
400                                 goto general_case;
401 #else
402                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
403 #endif
404                         }
405                 }
406                 if (!dlen) {
407                         /* Even if we fast path we should note if we ran out of room. */
408                         if (((slen != (size_t)-1) && slen) ||
409                                         ((slen == (size_t)-1) && lastp)) {
410                                 errno = E2BIG;
411                         }
412                 }
413                 return retval;
414         } else if (from == CH_UCS2 && to != CH_UCS2) {
415                 const unsigned char *p = (const unsigned char *)src;
416                 unsigned char *q = (unsigned char *)dest;
417                 size_t retval = 0;
418                 size_t slen = srclen;
419                 size_t dlen = destlen;
420                 unsigned char lastp = '\0';
421
422                 /* If all characters are ascii, fast path here. */
423                 while (((slen == (size_t)-1) || (slen >= 2)) && dlen) {
424                         if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
425                                 *q++ = *p;
426                                 if (slen != (size_t)-1) {
427                                         slen -= 2;
428                                 }
429                                 p += 2;
430                                 dlen--;
431                                 retval++;
432                                 if (!lastp)
433                                         break;
434                         } else {
435 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
436                                 goto general_case;
437 #else
438                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
439 #endif
440                         }
441                 }
442                 if (!dlen) {
443                         /* Even if we fast path we should note if we ran out of room. */
444                         if (((slen != (size_t)-1) && slen) ||
445                                         ((slen == (size_t)-1) && lastp)) {
446                                 errno = E2BIG;
447                         }
448                 }
449                 return retval;
450         } else if (from != CH_UCS2 && to == CH_UCS2) {
451                 const unsigned char *p = (const unsigned char *)src;
452                 unsigned char *q = (unsigned char *)dest;
453                 size_t retval = 0;
454                 size_t slen = srclen;
455                 size_t dlen = destlen;
456                 unsigned char lastp = '\0';
457
458                 /* If all characters are ascii, fast path here. */
459                 while (slen && (dlen >= 2)) {
460                         if ((lastp = *p) <= 0x7F) {
461                                 *q++ = *p++;
462                                 *q++ = '\0';
463                                 if (slen != (size_t)-1) {
464                                         slen--;
465                                 }
466                                 dlen -= 2;
467                                 retval += 2;
468                                 if (!lastp)
469                                         break;
470                         } else {
471 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
472                                 goto general_case;
473 #else
474                                 return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);
475 #endif
476                         }
477                 }
478                 if (!dlen) {
479                         /* Even if we fast path we should note if we ran out of room. */
480                         if (((slen != (size_t)-1) && slen) ||
481                                         ((slen == (size_t)-1) && lastp)) {
482                                 errno = E2BIG;
483                         }
484                 }
485                 return retval;
486         }
487
488 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
489   general_case:
490 #endif
491         return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);
492 }
493
494 /**
495  * Convert between character sets, allocating a new buffer for the result.
496  *
497  * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
498  * @param srclen length of source buffer.
499  * @param dest always set at least to NULL
500  * @note -1 is not accepted for srclen.
501  *
502  * @returns Size in bytes of the converted string; or -1 in case of error.
503  *
504  * Ensure the srclen contains the terminating zero.
505  * 
506  * I hate the goto's in this function. It's embarressing.....
507  * There has to be a cleaner way to do this. JRA.
508  **/
509
510 size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
511                                void const *src, size_t srclen, void **dest, BOOL allow_bad_conv)
512 {
513         size_t i_len, o_len, destlen = MAX(srclen, 512);
514         size_t retval;
515         const char *inbuf = (const char *)src;
516         char *outbuf = NULL, *ob = NULL;
517         smb_iconv_t descriptor;
518
519         *dest = NULL;
520
521         if (src == NULL || srclen == (size_t)-1)
522                 return (size_t)-1;
523         if (srclen == 0)
524                 return 0;
525
526         lazy_initialize_conv();
527
528         descriptor = conv_handles[from][to];
529
530         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
531                 if (!conv_silent)
532                         DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
533                 return (size_t)-1;
534         }
535
536   convert:
537
538         if ((destlen*2) < destlen) {
539                 /* wrapped ! abort. */
540                 if (!conv_silent)
541                         DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
542                 if (!ctx)
543                         SAFE_FREE(outbuf);
544                 return (size_t)-1;
545         } else {
546                 destlen = destlen * 2;
547         }
548
549         if (ctx)
550                 ob = (char *)TALLOC_REALLOC(ctx, ob, destlen);
551         else
552                 ob = (char *)SMB_REALLOC(ob, destlen);
553
554         if (!ob) {
555                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
556                 if (!ctx)
557                         SAFE_FREE(outbuf);
558                 return (size_t)-1;
559         } else {
560                 outbuf = ob;
561         }
562         i_len = srclen;
563         o_len = destlen;
564
565  again:
566
567         retval = smb_iconv(descriptor,
568                            &inbuf, &i_len,
569                            &outbuf, &o_len);
570         if(retval == (size_t)-1)                {
571                 const char *reason="unknown error";
572                 switch(errno) {
573                         case EINVAL:
574                                 reason="Incomplete multibyte sequence";
575                                 if (!conv_silent)
576                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
577                                 if (allow_bad_conv)
578                                         goto use_as_is;
579                                 break;
580                         case E2BIG:
581                                 goto convert;           
582                         case EILSEQ:
583                                 reason="Illegal multibyte sequence";
584                                 if (!conv_silent)
585                                         DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
586                                 if (allow_bad_conv)
587                                         goto use_as_is;
588                                 break;
589                 }
590                 if (!conv_silent)
591                         DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
592                 /* smb_panic(reason); */
593                 return (size_t)-1;
594         }
595
596   out:
597
598         destlen = destlen - o_len;
599         if (ctx)
600                 *dest = (char *)TALLOC_REALLOC(ctx,ob,destlen);
601         else
602                 *dest = (char *)SMB_REALLOC(ob,destlen);
603         if (destlen && !*dest) {
604                 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
605                 if (!ctx)
606                         SAFE_FREE(ob);
607                 return (size_t)-1;
608         }
609
610         return destlen;
611
612  use_as_is:
613
614         /* 
615          * Conversion not supported. This is actually an error, but there are so
616          * many misconfigured iconv systems and smb.conf's out there we can't just
617          * fail. Do a very bad conversion instead.... JRA.
618          */
619
620         {
621                 if (o_len == 0 || i_len == 0)
622                         goto out;
623
624                 if (from == CH_UCS2 && to != CH_UCS2) {
625                         /* Can't convert from ucs2 to multibyte. Just use the default fail char. */
626                         if (i_len < 2)
627                                 goto out;
628
629                         if (i_len >= 2) {
630                                 *outbuf = lp_failed_convert_char();
631
632                                 outbuf++;
633                                 o_len--;
634
635                                 inbuf += 2;
636                                 i_len -= 2;
637                         }
638
639                         if (o_len == 0 || i_len == 0)
640                                 goto out;
641
642                         /* Keep trying with the next char... */
643                         goto again;
644
645                 } else if (from != CH_UCS2 && to == CH_UCS2) {
646                         /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */
647                         if (o_len < 2)
648                                 goto out;
649
650                         outbuf[0] = lp_failed_convert_char();
651                         outbuf[1] = '\0';
652
653                         inbuf++;
654                         i_len--;
655
656                         outbuf += 2;
657                         o_len -= 2;
658
659                         if (o_len == 0 || i_len == 0)
660                                 goto out;
661
662                         /* Keep trying with the next char... */
663                         goto again;
664
665                 } else if (from != CH_UCS2 && to != CH_UCS2) {
666                         /* Failed multibyte to multibyte. Just copy the default fail char and
667                                 try again. */
668                         outbuf[0] = lp_failed_convert_char();
669
670                         inbuf++;
671                         i_len--;
672
673                         outbuf++;
674                         o_len--;
675
676                         if (o_len == 0 || i_len == 0)
677                                 goto out;
678
679                         /* Keep trying with the next char... */
680                         goto again;
681
682                 } else {
683                         /* Keep compiler happy.... */
684                         goto out;
685                 }
686         }
687 }
688
689 /**
690  * Convert between character sets, allocating a new buffer using talloc for the result.
691  *
692  * @param srclen length of source buffer.
693  * @param dest always set at least to NULL 
694  * @note -1 is not accepted for srclen.
695  *
696  * @returns Size in bytes of the converted string; or -1 in case of error.
697  **/
698 static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
699                                 void const *src, size_t srclen, void **dest, BOOL allow_bad_conv)
700 {
701         size_t dest_len;
702
703         *dest = NULL;
704         dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, allow_bad_conv);
705         if (dest_len == (size_t)-1)
706                 return (size_t)-1;
707         if (*dest == NULL)
708                 return (size_t)-1;
709         return dest_len;
710 }
711
712 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
713 {
714         size_t size;
715         smb_ucs2_t *buffer;
716         
717         size = push_ucs2_allocate(&buffer, src);
718         if (size == (size_t)-1) {
719                 smb_panic("failed to create UCS2 buffer");
720         }
721         if (!strupper_w(buffer) && (dest == src)) {
722                 free(buffer);
723                 return srclen;
724         }
725         
726         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True);
727         free(buffer);
728         return size;
729 }
730
731 /**
732  strdup() a unix string to upper case.
733  Max size is pstring.
734 **/
735
736 char *strdup_upper(const char *s)
737 {
738         pstring out_buffer;
739         const unsigned char *p = (const unsigned char *)s;
740         unsigned char *q = (unsigned char *)out_buffer;
741
742         /* this is quite a common operation, so we want it to be
743            fast. We optimise for the ascii case, knowing that all our
744            supported multi-byte character sets are ascii-compatible
745            (ie. they match for the first 128 chars) */
746
747         while (1) {
748                 if (*p & 0x80)
749                         break;
750                 *q++ = toupper(*p);
751                 if (!*p)
752                         break;
753                 p++;
754                 if (p - ( const unsigned char *)s >= sizeof(pstring))
755                         break;
756         }
757
758         if (*p) {
759                 /* MB case. */
760                 size_t size;
761                 wpstring buffer;
762                 size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer), True);
763                 if (size == (size_t)-1) {
764                         return NULL;
765                 }
766
767                 strupper_w(buffer);
768         
769                 size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True);
770                 if (size == (size_t)-1) {
771                         return NULL;
772                 }
773         }
774
775         return SMB_STRDUP(out_buffer);
776 }
777
778 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
779 {
780         size_t size;
781         smb_ucs2_t *buffer = NULL;
782         
783         size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
784                                        (void **) &buffer, True);
785         if (size == (size_t)-1 || !buffer) {
786                 smb_panic("failed to create UCS2 buffer");
787         }
788         if (!strlower_w(buffer) && (dest == src)) {
789                 SAFE_FREE(buffer);
790                 return srclen;
791         }
792         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True);
793         SAFE_FREE(buffer);
794         return size;
795 }
796
797 /**
798  strdup() a unix string to lower case.
799 **/
800
801 char *strdup_lower(const char *s)
802 {
803         size_t size;
804         smb_ucs2_t *buffer = NULL;
805         char *out_buffer;
806         
807         size = push_ucs2_allocate(&buffer, s);
808         if (size == -1 || !buffer) {
809                 return NULL;
810         }
811
812         strlower_w(buffer);
813         
814         size = pull_ucs2_allocate(&out_buffer, buffer);
815         SAFE_FREE(buffer);
816
817         if (size == (size_t)-1) {
818                 return NULL;
819         }
820         
821         return out_buffer;
822 }
823
824 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
825 {
826         if (flags & (STR_NOALIGN|STR_ASCII))
827                 return 0;
828         return PTR_DIFF(p, base_ptr) & 1;
829 }
830
831
832 /**
833  * Copy a string from a char* unix src to a dos codepage string destination.
834  *
835  * @return the number of bytes occupied by the string in the destination.
836  *
837  * @param flags can include
838  * <dl>
839  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
840  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
841  * </dl>
842  *
843  * @param dest_len the maximum length in bytes allowed in the
844  * destination.  If @p dest_len is -1 then no maximum is used.
845  **/
846 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
847 {
848         size_t src_len = strlen(src);
849         pstring tmpbuf;
850
851         /* treat a pstring as "unlimited" length */
852         if (dest_len == (size_t)-1)
853                 dest_len = sizeof(pstring);
854
855         if (flags & STR_UPPER) {
856                 pstrcpy(tmpbuf, src);
857                 strupper_m(tmpbuf);
858                 src = tmpbuf;
859         }
860
861         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
862                 src_len++;
863
864         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);
865 }
866
867 size_t push_ascii_fstring(void *dest, const char *src)
868 {
869         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
870 }
871
872 size_t push_ascii_pstring(void *dest, const char *src)
873 {
874         return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
875 }
876
877 /********************************************************************
878  Push an nstring - ensure null terminated. Written by
879  moriyama@miraclelinux.com (MORIYAMA Masayuki).
880 ********************************************************************/
881
882 size_t push_ascii_nstring(void *dest, const char *src)
883 {
884         size_t i, buffer_len, dest_len;
885         smb_ucs2_t *buffer;
886
887         conv_silent = True;
888         buffer_len = push_ucs2_allocate(&buffer, src);
889         if (buffer_len == (size_t)-1) {
890                 smb_panic("failed to create UCS2 buffer");
891         }
892
893         /* We're using buffer_len below to count ucs2 characters, not bytes. */
894         buffer_len /= sizeof(smb_ucs2_t);
895
896         dest_len = 0;
897         for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) {
898                 unsigned char mb[10];
899                 /* Convert one smb_ucs2_t character at a time. */
900                 size_t mb_len = convert_string(CH_UCS2, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
901                 if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
902                         memcpy((char *)dest + dest_len, mb, mb_len);
903                         dest_len += mb_len;
904                 } else {
905                         errno = E2BIG;
906                         break;
907                 }
908         }
909         ((char *)dest)[dest_len] = '\0';
910
911         SAFE_FREE(buffer);
912         conv_silent = False;
913         return dest_len;
914 }
915
916 /**
917  * Copy a string from a dos codepage source to a unix char* destination.
918  *
919  * The resulting string in "dest" is always null terminated.
920  *
921  * @param flags can have:
922  * <dl>
923  * <dt>STR_TERMINATE</dt>
924  * <dd>STR_TERMINATE means the string in @p src
925  * is null terminated, and src_len is ignored.</dd>
926  * </dl>
927  *
928  * @param src_len is the length of the source area in bytes.
929  * @returns the number of bytes occupied by the string in @p src.
930  **/
931 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
932 {
933         size_t ret;
934
935         if (dest_len == (size_t)-1)
936                 dest_len = sizeof(pstring);
937
938         if (flags & STR_TERMINATE) {
939                 if (src_len == (size_t)-1) {
940                         src_len = strlen(src) + 1;
941                 } else {
942                         size_t len = strnlen(src, src_len);
943                         if (len < src_len)
944                                 len++;
945                         src_len = len;
946                 }
947         }
948
949         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, True);
950         if (ret == (size_t)-1) {
951                 dest_len = 0;
952         }
953
954         if (dest_len)
955                 dest[MIN(ret, dest_len-1)] = 0;
956         else 
957                 dest[0] = 0;
958
959         return src_len;
960 }
961
962 size_t pull_ascii_pstring(char *dest, const void *src)
963 {
964         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
965 }
966
967 size_t pull_ascii_fstring(char *dest, const void *src)
968 {
969         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
970 }
971
972 /* When pulling an nstring it can expand into a larger size (dos cp -> utf8). Cope with this. */
973
974 size_t pull_ascii_nstring(char *dest, size_t dest_len, const void *src)
975 {
976         return pull_ascii(dest, src, dest_len, sizeof(nstring)-1, STR_TERMINATE);
977 }
978
979 /**
980  * Copy a string from a char* src to a unicode destination.
981  *
982  * @returns the number of bytes occupied by the string in the destination.
983  *
984  * @param flags can have:
985  *
986  * <dl>
987  * <dt>STR_TERMINATE <dd>means include the null termination.
988  * <dt>STR_UPPER     <dd>means uppercase in the destination.
989  * <dt>STR_NOALIGN   <dd>means don't do alignment.
990  * </dl>
991  *
992  * @param dest_len is the maximum length allowed in the
993  * destination. If dest_len is -1 then no maxiumum is used.
994  **/
995
996 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
997 {
998         size_t len=0;
999         size_t src_len;
1000         size_t ret;
1001
1002         /* treat a pstring as "unlimited" length */
1003         if (dest_len == (size_t)-1)
1004                 dest_len = sizeof(pstring);
1005
1006         if (flags & STR_TERMINATE)
1007                 src_len = (size_t)-1;
1008         else
1009                 src_len = strlen(src);
1010
1011         if (ucs2_align(base_ptr, dest, flags)) {
1012                 *(char *)dest = 0;
1013                 dest = (void *)((char *)dest + 1);
1014                 if (dest_len)
1015                         dest_len--;
1016                 len++;
1017         }
1018
1019         /* ucs2 is always a multiple of 2 bytes */
1020         dest_len &= ~1;
1021
1022         ret =  convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len, True);
1023         if (ret == (size_t)-1) {
1024                 return 0;
1025         }
1026
1027         len += ret;
1028
1029         if (flags & STR_UPPER) {
1030                 smb_ucs2_t *dest_ucs2 = dest;
1031                 size_t i;
1032                 for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
1033                         smb_ucs2_t v = toupper_w(dest_ucs2[i]);
1034                         if (v != dest_ucs2[i]) {
1035                                 dest_ucs2[i] = v;
1036                         }
1037                 }
1038         }
1039
1040         return len;
1041 }
1042
1043
1044 /**
1045  * Copy a string from a unix char* src to a UCS2 destination,
1046  * allocating a buffer using talloc().
1047  *
1048  * @param dest always set at least to NULL 
1049  *
1050  * @returns The number of bytes occupied by the string in the destination
1051  *         or -1 in case of error.
1052  **/
1053 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
1054 {
1055         size_t src_len = strlen(src)+1;
1056
1057         *dest = NULL;
1058         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True);
1059 }
1060
1061
1062 /**
1063  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
1064  *
1065  * @param dest always set at least to NULL 
1066  *
1067  * @returns The number of bytes occupied by the string in the destination
1068  *         or -1 in case of error.
1069  **/
1070
1071 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
1072 {
1073         size_t src_len = strlen(src)+1;
1074
1075         *dest = NULL;
1076         return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest, True);
1077 }
1078
1079 /**
1080  Copy a string from a char* src to a UTF-8 destination.
1081  Return the number of bytes occupied by the string in the destination
1082  Flags can have:
1083   STR_TERMINATE means include the null termination
1084   STR_UPPER     means uppercase in the destination
1085  dest_len is the maximum length allowed in the destination. If dest_len
1086  is -1 then no maxiumum is used.
1087 **/
1088
1089 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
1090 {
1091         size_t src_len = strlen(src);
1092         pstring tmpbuf;
1093
1094         /* treat a pstring as "unlimited" length */
1095         if (dest_len == (size_t)-1)
1096                 dest_len = sizeof(pstring);
1097
1098         if (flags & STR_UPPER) {
1099                 pstrcpy(tmpbuf, src);
1100                 strupper_m(tmpbuf);
1101                 src = tmpbuf;
1102         }
1103
1104         if (flags & STR_TERMINATE)
1105                 src_len++;
1106
1107         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len, True);
1108 }
1109
1110 size_t push_utf8_fstring(void *dest, const char *src)
1111 {
1112         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
1113 }
1114
1115 /**
1116  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
1117  *
1118  * @param dest always set at least to NULL 
1119  *
1120  * @returns The number of bytes occupied by the string in the destination
1121  **/
1122
1123 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1124 {
1125         size_t src_len = strlen(src)+1;
1126
1127         *dest = NULL;
1128         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest, True);
1129 }
1130
1131 /**
1132  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
1133  *
1134  * @param dest always set at least to NULL 
1135  *
1136  * @returns The number of bytes occupied by the string in the destination
1137  **/
1138
1139 size_t push_utf8_allocate(char **dest, const char *src)
1140 {
1141         size_t src_len = strlen(src)+1;
1142
1143         *dest = NULL;
1144         return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest, True);      
1145 }
1146
1147 /**
1148  Copy a string from a ucs2 source to a unix char* destination.
1149  Flags can have:
1150   STR_TERMINATE means the string in src is null terminated.
1151   STR_NOALIGN   means don't try to align.
1152  if STR_TERMINATE is set then src_len is ignored if it is -1.
1153  src_len is the length of the source area in bytes
1154  Return the number of bytes occupied by the string in src.
1155  The resulting string in "dest" is always null terminated.
1156 **/
1157
1158 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1159 {
1160         size_t ret;
1161
1162         if (dest_len == (size_t)-1)
1163                 dest_len = sizeof(pstring);
1164
1165         if (ucs2_align(base_ptr, src, flags)) {
1166                 src = (const void *)((const char *)src + 1);
1167                 if (src_len != (size_t)-1)
1168                         src_len--;
1169         }
1170
1171         if (flags & STR_TERMINATE) {
1172                 /* src_len -1 is the default for null terminated strings. */
1173                 if (src_len != (size_t)-1) {
1174                         size_t len = strnlen_w(src, src_len/2);
1175                         if (len < src_len/2)
1176                                 len++;
1177                         src_len = len*2;
1178                 }
1179         }
1180
1181         /* ucs2 is always a multiple of 2 bytes */
1182         if (src_len != (size_t)-1)
1183                 src_len &= ~1;
1184         
1185         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len, True);
1186         if (ret == (size_t)-1) {
1187                 return 0;
1188         }
1189
1190         if (src_len == (size_t)-1)
1191                 src_len = ret*2;
1192                 
1193         if (dest_len)
1194                 dest[MIN(ret, dest_len-1)] = 0;
1195         else 
1196                 dest[0] = 0;
1197
1198         return src_len;
1199 }
1200
1201 size_t pull_ucs2_pstring(char *dest, const void *src)
1202 {
1203         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
1204 }
1205
1206 size_t pull_ucs2_fstring(char *dest, const void *src)
1207 {
1208         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
1209 }
1210
1211 /**
1212  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1213  *
1214  * @param dest always set at least to NULL 
1215  *
1216  * @returns The number of bytes occupied by the string in the destination
1217  **/
1218
1219 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
1220 {
1221         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1222         *dest = NULL;
1223         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True);
1224 }
1225
1226 /**
1227  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
1228  *
1229  * @param dest always set at least to NULL 
1230  *
1231  * @returns The number of bytes occupied by the string in the destination
1232  **/
1233
1234 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
1235 {
1236         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
1237         *dest = NULL;
1238         return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest, True);
1239 }
1240
1241 /**
1242  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1243  *
1244  * @param dest always set at least to NULL 
1245  *
1246  * @returns The number of bytes occupied by the string in the destination
1247  **/
1248
1249 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1250 {
1251         size_t src_len = strlen(src)+1;
1252         *dest = NULL;
1253         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1254 }
1255
1256 /**
1257  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
1258  *
1259  * @param dest always set at least to NULL 
1260  *
1261  * @returns The number of bytes occupied by the string in the destination
1262  **/
1263
1264 size_t pull_utf8_allocate(char **dest, const char *src)
1265 {
1266         size_t src_len = strlen(src)+1;
1267         *dest = NULL;
1268         return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True);
1269 }
1270  
1271 /**
1272  * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
1273  *
1274  * @param dest always set at least to NULL 
1275  *
1276  * @returns The number of bytes occupied by the string in the destination
1277  **/
1278
1279 size_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1280 {
1281         size_t src_len = strlen(src)+1;
1282         *dest = NULL;
1283         return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, True);
1284 }
1285
1286 /**
1287  Copy a string from a char* src to a unicode or ascii
1288  dos codepage destination choosing unicode or ascii based on the 
1289  flags in the SMB buffer starting at base_ptr.
1290  Return the number of bytes occupied by the string in the destination.
1291  flags can have:
1292   STR_TERMINATE means include the null termination.
1293   STR_UPPER     means uppercase in the destination.
1294   STR_ASCII     use ascii even with unicode packet.
1295   STR_NOALIGN   means don't do alignment.
1296  dest_len is the maximum length allowed in the destination. If dest_len
1297  is -1 then no maxiumum is used.
1298 **/
1299
1300 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)
1301 {
1302 #ifdef DEVELOPER
1303         /* We really need to zero fill here, not clobber
1304          * region, as we want to ensure that valgrind thinks
1305          * all of the outgoing buffer has been written to
1306          * so a send() or write() won't trap an error.
1307          * JRA.
1308          */
1309 #if 0
1310         if (dest_len != (size_t)-1)
1311                 clobber_region(function, line, dest, dest_len);
1312 #else
1313         if (dest_len != (size_t)-1)
1314                 memset(dest, '\0', dest_len);
1315 #endif
1316 #endif
1317
1318         if (!(flags & STR_ASCII) && \
1319             ((flags & STR_UNICODE || \
1320               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1321                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
1322         }
1323         return push_ascii(dest, src, dest_len, flags);
1324 }
1325
1326
1327 /**
1328  Copy a string from a unicode or ascii source (depending on
1329  the packet flags) to a char* destination.
1330  Flags can have:
1331   STR_TERMINATE means the string in src is null terminated.
1332   STR_UNICODE   means to force as unicode.
1333   STR_ASCII     use ascii even with unicode packet.
1334   STR_NOALIGN   means don't do alignment.
1335  if STR_TERMINATE is set then src_len is ignored is it is -1
1336  src_len is the length of the source area in bytes.
1337  Return the number of bytes occupied by the string in src.
1338  The resulting string in "dest" is always null terminated.
1339 **/
1340
1341 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)
1342 {
1343 #ifdef DEVELOPER
1344         if (dest_len != (size_t)-1)
1345                 clobber_region(function, line, dest, dest_len);
1346 #endif
1347
1348         if (!(flags & STR_ASCII) && \
1349             ((flags & STR_UNICODE || \
1350               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1351                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1352         }
1353         return pull_ascii(dest, src, dest_len, src_len, flags);
1354 }
1355
1356 size_t align_string(const void *base_ptr, const char *p, int flags)
1357 {
1358         if (!(flags & STR_ASCII) && \
1359             ((flags & STR_UNICODE || \
1360               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1361                 return ucs2_align(base_ptr, p, flags);
1362         }
1363         return 0;
1364 }
1365
1366 /****************************************************************
1367  Calculate the size (in bytes) of the next multibyte character in
1368  our internal character set. Note that p must be pointing to a
1369  valid mb char, not within one.
1370 ****************************************************************/
1371
1372 size_t next_mb_char_size(const char *s)
1373 {
1374         size_t i;
1375
1376         if (!(*s & 0x80))
1377                 return 1; /* ascii. */
1378
1379         conv_silent = True;
1380         for ( i = 1; i <=4; i++ ) {
1381                 smb_ucs2_t uc;
1382                 if (convert_string(CH_UNIX, CH_UCS2, s, i, &uc, 2, False) == 2) {
1383 #if 0 /* JRATEST */
1384                         DEBUG(10,("next_mb_char_size: size %u at string %s\n",
1385                                 (unsigned int)i, s));
1386 #endif
1387                         conv_silent = False;
1388                         return i;
1389                 }
1390         }
1391         /* We're hosed - we don't know how big this is... */
1392         DEBUG(10,("next_mb_char_size: unknown size at string %s\n", s));
1393         conv_silent = False;
1394         return 1;
1395 }