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