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