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