Release alpha15.
[nivanova/samba-autobuild/.git] / source3 / lib / charcnv.c
1 /*
2    Unix SMB/CIFS implementation.
3    Character set conversion Extensions
4    Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5    Copyright (C) Andrew Tridgell 2001
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Martin Pool 2003
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 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  * Destroy global objects allocated by init_iconv()
27  **/
28 void gfree_charcnv(void)
29 {
30         TALLOC_FREE(global_iconv_handle);
31 }
32
33 /**
34  * Initialize iconv conversion descriptors.
35  *
36  * This is called the first time it is needed, and also called again
37  * every time the configuration is reloaded, because the charset or
38  * codepage might have changed.
39  **/
40 void init_iconv(void)
41 {
42         global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
43                                                                 lp_unix_charset(), lp_display_charset(),
44                                                                 true, global_iconv_handle);
45 }
46
47 /**
48  talloc_strdup() a unix string to upper case.
49 **/
50
51 char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *s)
52 {
53         char *out_buffer = talloc_strdup(ctx,s);
54         const unsigned char *p = (const unsigned char *)s;
55         unsigned char *q = (unsigned char *)out_buffer;
56
57         if (!q) {
58                 return NULL;
59         }
60
61         /* this is quite a common operation, so we want it to be
62            fast. We optimise for the ascii case, knowing that all our
63            supported multi-byte character sets are ascii-compatible
64            (ie. they match for the first 128 chars) */
65
66         while (*p) {
67                 if (*p & 0x80)
68                         break;
69                 *q++ = toupper_ascii_fast(*p);
70                 p++;
71         }
72
73         if (*p) {
74                 /* MB case. */
75                 size_t converted_size, converted_size2;
76                 smb_ucs2_t *ubuf = NULL;
77
78                 /* We're not using the ascii buffer above. */
79                 TALLOC_FREE(out_buffer);
80
81                 if (!convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, s,
82                                            strlen(s)+1, (void *)&ubuf,
83                                            &converted_size))
84                 {
85                         return NULL;
86                 }
87
88                 strupper_w(ubuf);
89
90                 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, ubuf,
91                                            converted_size, (void *)&out_buffer,
92                                            &converted_size2))
93                 {
94                         TALLOC_FREE(ubuf);
95                         return NULL;
96                 }
97
98                 /* Don't need the intermediate buffer
99                  * anymore.
100                  */
101                 TALLOC_FREE(ubuf);
102         }
103
104         return out_buffer;
105 }
106
107 char *strupper_talloc(TALLOC_CTX *ctx, const char *s) {
108         return talloc_strdup_upper(ctx, s);
109 }
110
111
112 char *talloc_strdup_lower(TALLOC_CTX *ctx, const char *s)
113 {
114         size_t converted_size;
115         smb_ucs2_t *buffer = NULL;
116         char *out_buffer;
117
118         if (!push_ucs2_talloc(ctx, &buffer, s, &converted_size)) {
119                 return NULL;
120         }
121
122         strlower_w(buffer);
123
124         if (!pull_ucs2_talloc(ctx, &out_buffer, buffer, &converted_size)) {
125                 TALLOC_FREE(buffer);
126                 return NULL;
127         }
128
129         TALLOC_FREE(buffer);
130
131         return out_buffer;
132 }
133
134 char *strlower_talloc(TALLOC_CTX *ctx, const char *s) {
135         return talloc_strdup_lower(ctx, s);
136 }
137
138
139 /**
140  * Copy a string from a char* unix src to a dos codepage string destination.
141  *
142  * @return the number of bytes occupied by the string in the destination.
143  *
144  * @param flags can include
145  * <dl>
146  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
147  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
148  * </dl>
149  *
150  * @param dest_len the maximum length in bytes allowed in the
151  * destination.
152  **/
153 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
154 {
155         size_t src_len = strlen(src);
156         char *tmpbuf = NULL;
157         size_t size;
158         bool ret;
159
160         /* No longer allow a length of -1. */
161         if (dest_len == (size_t)-1) {
162                 smb_panic("push_ascii - dest_len == -1");
163         }
164
165         if (flags & STR_UPPER) {
166                 tmpbuf = SMB_STRDUP(src);
167                 if (!tmpbuf) {
168                         smb_panic("malloc fail");
169                 }
170                 strupper_m(tmpbuf);
171                 src = tmpbuf;
172         }
173
174         if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
175                 src_len++;
176         }
177
178         ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, &size);
179         if (ret == false &&
180                         (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
181                         && dest_len > 0) {
182                 ((char *)dest)[0] = '\0';
183         }
184         SAFE_FREE(tmpbuf);
185         return ret ? size : (size_t)-1;
186 }
187
188 /********************************************************************
189  Push and malloc an ascii string. src and dest null terminated.
190 ********************************************************************/
191
192 bool push_ascii_talloc(TALLOC_CTX *mem_ctx, char **dest, const char *src, size_t *converted_size)
193 {
194         size_t src_len = strlen(src)+1;
195
196         *dest = NULL;
197         return convert_string_talloc(mem_ctx, CH_UNIX, CH_DOS, src, src_len,
198                                      (void **)dest, converted_size);
199 }
200
201 /**
202  * Copy a string from a dos codepage source to a unix char* destination.
203  *
204  * The resulting string in "dest" is always null terminated.
205  *
206  * @param flags can have:
207  * <dl>
208  * <dt>STR_TERMINATE</dt>
209  * <dd>STR_TERMINATE means the string in @p src
210  * is null terminated, and src_len is ignored.</dd>
211  * </dl>
212  *
213  * @param src_len is the length of the source area in bytes.
214  * @returns the number of bytes occupied by the string in @p src.
215  **/
216 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
217 {
218         bool ret;
219         size_t size = 0;
220
221         if (dest_len == (size_t)-1) {
222                 /* No longer allow dest_len of -1. */
223                 smb_panic("pull_ascii - invalid dest_len of -1");
224         }
225
226         if (flags & STR_TERMINATE) {
227                 if (src_len == (size_t)-1) {
228                         src_len = strlen((const char *)src) + 1;
229                 } else {
230                         size_t len = strnlen((const char *)src, src_len);
231                         if (len < src_len)
232                                 len++;
233                         src_len = len;
234                 }
235         }
236
237         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, &size);
238         if (ret == false) {
239                 size = 0;
240                 dest_len = 0;
241         }
242
243         if (dest_len && size) {
244                 /* Did we already process the terminating zero ? */
245                 if (dest[MIN(size-1, dest_len-1)] != 0) {
246                         dest[MIN(size, dest_len-1)] = 0;
247                 }
248         } else  {
249                 dest[0] = 0;
250         }
251
252         return src_len;
253 }
254
255 /**
256  * Copy a string from a dos codepage source to a unix char* destination.
257  * Talloc version.
258  *
259  * The resulting string in "dest" is always null terminated.
260  *
261  * @param flags can have:
262  * <dl>
263  * <dt>STR_TERMINATE</dt>
264  * <dd>STR_TERMINATE means the string in @p src
265  * is null terminated, and src_len is ignored.</dd>
266  * </dl>
267  *
268  * @param src_len is the length of the source area in bytes.
269  * @returns the number of bytes occupied by the string in @p src.
270  **/
271
272 static size_t pull_ascii_base_talloc(TALLOC_CTX *ctx,
273                                      char **ppdest,
274                                      const void *src,
275                                      size_t src_len,
276                                      int flags)
277 {
278         char *dest = NULL;
279         size_t dest_len;
280
281         *ppdest = NULL;
282
283         if (!src_len) {
284                 return 0;
285         }
286
287         if (src_len == (size_t)-1) {
288                 smb_panic("sec_len == -1 in pull_ascii_base_talloc");
289         }
290
291         if (flags & STR_TERMINATE) {
292                 size_t len = strnlen((const char *)src, src_len);
293                 if (len < src_len)
294                         len++;
295                 src_len = len;
296                 /* Ensure we don't use an insane length from the client. */
297                 if (src_len >= 1024*1024) {
298                         char *msg = talloc_asprintf(ctx,
299                                         "Bad src length (%u) in "
300                                         "pull_ascii_base_talloc",
301                                         (unsigned int)src_len);
302                         smb_panic(msg);
303                 }
304         }
305
306         /* src_len != -1 here. */
307
308         if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
309                                      &dest_len)) {
310                 dest_len = 0;
311         }
312
313         if (dest_len && dest) {
314                 /* Did we already process the terminating zero ? */
315                 if (dest[dest_len-1] != 0) {
316                         size_t size = talloc_get_size(dest);
317                         /* Have we got space to append the '\0' ? */
318                         if (size <= dest_len) {
319                                 /* No, realloc. */
320                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
321                                                 dest_len+1);
322                                 if (!dest) {
323                                         /* talloc fail. */
324                                         dest_len = (size_t)-1;
325                                         return 0;
326                                 }
327                         }
328                         /* Yay - space ! */
329                         dest[dest_len] = '\0';
330                         dest_len++;
331                 }
332         } else if (dest) {
333                 dest[0] = 0;
334         }
335
336         *ppdest = dest;
337         return src_len;
338 }
339
340 /**
341  * Copy a string from a char* src to a unicode destination.
342  *
343  * @returns the number of bytes occupied by the string in the destination.
344  *
345  * @param flags can have:
346  *
347  * <dl>
348  * <dt>STR_TERMINATE <dd>means include the null termination.
349  * <dt>STR_UPPER     <dd>means uppercase in the destination.
350  * <dt>STR_NOALIGN   <dd>means don't do alignment.
351  * </dl>
352  *
353  * @param dest_len is the maximum length allowed in the
354  * destination.
355  **/
356
357 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
358 {
359         size_t len=0;
360         size_t src_len;
361         size_t size = 0;
362         bool ret;
363
364         if (dest_len == (size_t)-1) {
365                 /* No longer allow dest_len of -1. */
366                 smb_panic("push_ucs2 - invalid dest_len of -1");
367         }
368
369         if (flags & STR_TERMINATE)
370                 src_len = (size_t)-1;
371         else
372                 src_len = strlen(src);
373
374         if (ucs2_align(base_ptr, dest, flags)) {
375                 *(char *)dest = 0;
376                 dest = (void *)((char *)dest + 1);
377                 if (dest_len)
378                         dest_len--;
379                 len++;
380         }
381
382         /* ucs2 is always a multiple of 2 bytes */
383         dest_len &= ~1;
384
385         ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, &size);
386         if (ret == false) {
387                 if ((flags & STR_TERMINATE) &&
388                                 dest &&
389                                 dest_len) {
390                         *(char *)dest = 0;
391                 }
392                 return len;
393         }
394
395         len += size;
396
397         if (flags & STR_UPPER) {
398                 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
399                 size_t i;
400
401                 /* We check for i < (ret / 2) below as the dest string isn't null
402                    terminated if STR_TERMINATE isn't set. */
403
404                 for (i = 0; i < (ret / 2) && i < (dest_len / 2) && dest_ucs2[i]; i++) {
405                         smb_ucs2_t v = toupper_m(dest_ucs2[i]);
406                         if (v != dest_ucs2[i]) {
407                                 dest_ucs2[i] = v;
408                         }
409                 }
410         }
411
412         return len;
413 }
414
415
416 /**
417  * Copy a string from a unix char* src to a UCS2 destination,
418  * allocating a buffer using talloc().
419  *
420  * @param dest always set at least to NULL 
421  * @parm converted_size set to the number of bytes occupied by the string in
422  * the destination on success.
423  *
424  * @return true if new buffer was correctly allocated, and string was
425  * converted.
426  **/
427 bool push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src,
428                       size_t *converted_size)
429 {
430         size_t src_len = strlen(src)+1;
431
432         *dest = NULL;
433         return convert_string_talloc(ctx, CH_UNIX, CH_UTF16LE, src, src_len,
434                                      (void **)dest, converted_size);
435 }
436
437
438 /**
439  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
440  *
441  * @param dest always set at least to NULL 
442  * @parm converted_size set to the number of bytes occupied by the string in
443  * the destination on success.
444  *
445  * @return true if new buffer was correctly allocated, and string was
446  * converted.
447  **/
448
449 bool push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
450                       size_t *converted_size)
451 {
452         size_t src_len = strlen(src)+1;
453
454         *dest = NULL;
455         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len,
456                                      (void**)dest, converted_size);
457 }
458
459 /**
460  Copy a string from a ucs2 source to a unix char* destination.
461  Flags can have:
462   STR_TERMINATE means the string in src is null terminated.
463   STR_NOALIGN   means don't try to align.
464  if STR_TERMINATE is set then src_len is ignored if it is -1.
465  src_len is the length of the source area in bytes
466  Return the number of bytes occupied by the string in src.
467  The resulting string in "dest" is always null terminated.
468 **/
469
470 static size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
471 {
472         size_t size = 0;
473         size_t ucs2_align_len = 0;
474         bool ret;
475
476         if (dest_len == (size_t)-1) {
477                 /* No longer allow dest_len of -1. */
478                 smb_panic("pull_ucs2 - invalid dest_len of -1");
479         }
480
481         if (!src_len) {
482                 if (dest && dest_len > 0) {
483                         dest[0] = '\0';
484                 }
485                 return 0;
486         }
487
488         if (ucs2_align(base_ptr, src, flags)) {
489                 src = (const void *)((const char *)src + 1);
490                 if (src_len != (size_t)-1)
491                         src_len--;
492                 ucs2_align_len = 1;
493         }
494
495         if (flags & STR_TERMINATE) {
496                 /* src_len -1 is the default for null terminated strings. */
497                 if (src_len != (size_t)-1) {
498                         size_t len = strnlen_w((const smb_ucs2_t *)src,
499                                                 src_len/2);
500                         if (len < src_len/2)
501                                 len++;
502                         src_len = len*2;
503                 }
504         }
505
506         /* ucs2 is always a multiple of 2 bytes */
507         if (src_len != (size_t)-1)
508                 src_len &= ~1;
509
510         ret = convert_string(CH_UTF16LE, CH_UNIX, src, src_len, dest, dest_len, &size);
511         if (ret == false) {
512                 size = 0;
513                 dest_len = 0;
514         }
515
516         if (src_len == (size_t)-1)
517                 src_len = size*2;
518
519         if (dest_len && size) {
520                 /* Did we already process the terminating zero ? */
521                 if (dest[MIN(size-1, dest_len-1)] != 0) {
522                         dest[MIN(size, dest_len-1)] = 0;
523                 }
524         } else {
525                 dest[0] = 0;
526         }
527
528         return src_len + ucs2_align_len;
529 }
530
531 /**
532  Copy a string from a ucs2 source to a unix char* destination.
533  Talloc version with a base pointer.
534  Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
535  needs fixing. JRA).
536  Flags can have:
537   STR_TERMINATE means the string in src is null terminated.
538   STR_NOALIGN   means don't try to align.
539  if STR_TERMINATE is set then src_len is ignored if it is -1.
540  src_len is the length of the source area in bytes
541  Return the number of bytes occupied by the string in src.
542  The resulting string in "dest" is always null terminated.
543 **/
544
545 static size_t pull_ucs2_base_talloc(TALLOC_CTX *ctx,
546                                     const void *base_ptr,
547                                     char **ppdest,
548                                     const void *src,
549                                     size_t src_len,
550                                     int flags)
551 {
552         char *dest;
553         size_t dest_len;
554         size_t ucs2_align_len = 0;
555
556         *ppdest = NULL;
557
558 #ifdef DEVELOPER
559         /* Ensure we never use the braindead "malloc" varient. */
560         if (ctx == NULL) {
561                 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
562         }
563 #endif
564
565         if (!src_len) {
566                 return 0;
567         }
568
569         if (src_len == (size_t)-1) {
570                 /* no longer used anywhere, but worth checking */
571                 smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
572         }
573
574         if (ucs2_align(base_ptr, src, flags)) {
575                 src = (const void *)((const char *)src + 1);
576                 src_len--;
577                 ucs2_align_len = 1;
578         }
579
580         if (flags & STR_TERMINATE) {
581                 /* src_len -1 is the default for null terminated strings. */
582                 size_t len = strnlen_w((const smb_ucs2_t *)src,
583                                        src_len/2);
584                 if (len < src_len/2)
585                         len++;
586                 src_len = len*2;
587
588                 /* Ensure we don't use an insane length from the client. */
589                 if (src_len >= 1024*1024) {
590                         smb_panic("Bad src length in pull_ucs2_base_talloc\n");
591                 }
592         }
593
594         /* ucs2 is always a multiple of 2 bytes */
595         src_len &= ~1;
596
597         if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
598                                    (void *)&dest, &dest_len)) {
599                 dest_len = 0;
600         }
601
602         if (dest_len) {
603                 /* Did we already process the terminating zero ? */
604                 if (dest[dest_len-1] != 0) {
605                         size_t size = talloc_get_size(dest);
606                         /* Have we got space to append the '\0' ? */
607                         if (size <= dest_len) {
608                                 /* No, realloc. */
609                                 dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
610                                                 dest_len+1);
611                                 if (!dest) {
612                                         /* talloc fail. */
613                                         dest_len = (size_t)-1;
614                                         return 0;
615                                 }
616                         }
617                         /* Yay - space ! */
618                         dest[dest_len] = '\0';
619                         dest_len++;
620                 }
621         } else if (dest) {
622                 dest[0] = 0;
623         }
624
625         *ppdest = dest;
626         return src_len + ucs2_align_len;
627 }
628
629 /**
630  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
631  *
632  * @param dest always set at least to NULL 
633  * @parm converted_size set to the number of bytes occupied by the string in
634  * the destination on success.
635  *
636  * @return true if new buffer was correctly allocated, and string was
637  * converted.
638  **/
639
640 bool pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src,
641                       size_t *converted_size)
642 {
643         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
644
645         *dest = NULL;
646         return convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
647                                      (void **)dest, converted_size);
648 }
649
650 /**
651  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
652  *
653  * @param dest always set at least to NULL 
654  * @parm converted_size set to the number of bytes occupied by the string in
655  * the destination on success.
656  *
657  * @return true if new buffer was correctly allocated, and string was
658  * converted.
659  **/
660
661 bool pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
662                       size_t *converted_size)
663 {
664         size_t src_len = strlen(src)+1;
665
666         *dest = NULL;
667         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len,
668                                      (void **)dest, converted_size);
669 }
670
671  
672 /**
673  * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
674  *
675  * @param dest always set at least to NULL 
676  * @parm converted_size set to the number of bytes occupied by the string in
677  * the destination on success.
678  *
679  * @return true if new buffer was correctly allocated, and string was
680  * converted.
681  **/
682
683 bool pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src,
684                        size_t *converted_size)
685 {
686         size_t src_len = strlen(src)+1;
687
688         *dest = NULL;
689         return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len,
690                                      (void **)dest, converted_size);
691 }
692
693 /**
694  Copy a string from a char* src to a unicode or ascii
695  dos codepage destination choosing unicode or ascii based on the 
696  flags supplied
697  Return the number of bytes occupied by the string in the destination.
698  flags can have:
699   STR_TERMINATE means include the null termination.
700   STR_UPPER     means uppercase in the destination.
701   STR_ASCII     use ascii even with unicode packet.
702   STR_NOALIGN   means don't do alignment.
703  dest_len is the maximum length allowed in the destination. If dest_len
704  is -1 then no maxiumum is used.
705 **/
706
707 size_t push_string_check_fn(void *dest, const char *src,
708                          size_t dest_len, int flags)
709 {
710         if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
711                 return push_ucs2(NULL, dest, src, dest_len, flags);
712         }
713         return push_ascii(dest, src, dest_len, flags);
714 }
715
716
717 /**
718  Copy a string from a char* src to a unicode or ascii
719  dos codepage destination choosing unicode or ascii based on the 
720  flags in the SMB buffer starting at base_ptr.
721  Return the number of bytes occupied by the string in the destination.
722  flags can have:
723   STR_TERMINATE means include the null termination.
724   STR_UPPER     means uppercase in the destination.
725   STR_ASCII     use ascii even with unicode packet.
726   STR_NOALIGN   means don't do alignment.
727  dest_len is the maximum length allowed in the destination. If dest_len
728  is -1 then no maxiumum is used.
729 **/
730
731 size_t push_string_base(const char *base, uint16 flags2,
732                         void *dest, const char *src,
733                         size_t dest_len, int flags)
734 {
735
736         if (!(flags & STR_ASCII) && \
737             ((flags & STR_UNICODE || \
738               (flags2 & FLAGS2_UNICODE_STRINGS)))) {
739                 return push_ucs2(base, dest, src, dest_len, flags);
740         }
741         return push_ascii(dest, src, dest_len, flags);
742 }
743
744 /**
745  Copy a string from a char* src to a unicode or ascii
746  dos codepage destination choosing unicode or ascii based on the 
747  flags supplied
748  Return the number of bytes occupied by the string in the destination.
749  flags can have:
750   STR_TERMINATE means include the null termination.
751   STR_UPPER     means uppercase in the destination.
752   STR_ASCII     use ascii even with unicode packet.
753   STR_NOALIGN   means don't do alignment.
754  dest_len is the maximum length allowed in the destination. If dest_len
755  is -1 then no maxiumum is used.
756 **/
757
758 ssize_t push_string(void *dest, const char *src, size_t dest_len, int flags)
759 {
760         size_t ret;
761
762         if (!(flags & STR_ASCII) && \
763             (flags & STR_UNICODE)) {
764                 ret = push_ucs2(NULL, dest, src, dest_len, flags);
765         } else {
766                 ret = push_ascii(dest, src, dest_len, flags);
767         }
768         if (ret == (size_t)-1) {
769                 return -1;
770         }
771         return ret;
772 }
773
774 /**
775  Copy a string from a unicode or ascii source (depending on
776  the packet flags) to a char* destination.
777  Flags can have:
778   STR_TERMINATE means the string in src is null terminated.
779   STR_UNICODE   means to force as unicode.
780   STR_ASCII     use ascii even with unicode packet.
781   STR_NOALIGN   means don't do alignment.
782  if STR_TERMINATE is set then src_len is ignored is it is -1
783  src_len is the length of the source area in bytes.
784  Return the number of bytes occupied by the string in src.
785  The resulting string in "dest" is always null terminated.
786 **/
787
788 size_t pull_string_fn(const void *base_ptr,
789                    uint16 smb_flags2,
790                    char *dest,
791                    const void *src,
792                    size_t dest_len,
793                    size_t src_len,
794                    int flags)
795 {
796         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
797                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
798                           "UNICODE defined");
799         }
800
801         if (!(flags & STR_ASCII) && \
802             ((flags & STR_UNICODE || \
803               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
804                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
805         }
806         return pull_ascii(dest, src, dest_len, src_len, flags);
807 }
808
809 /**
810  Copy a string from a unicode or ascii source (depending on
811  the packet flags) to a char* destination.
812  Variant that uses talloc.
813  Flags can have:
814   STR_TERMINATE means the string in src is null terminated.
815   STR_UNICODE   means to force as unicode.
816   STR_ASCII     use ascii even with unicode packet.
817   STR_NOALIGN   means don't do alignment.
818  if STR_TERMINATE is set then src_len is ignored is it is -1
819  src_len is the length of the source area in bytes.
820  Return the number of bytes occupied by the string in src.
821  The resulting string in "dest" is always null terminated.
822 **/
823
824 size_t pull_string_talloc(TALLOC_CTX *ctx,
825                           const void *base_ptr,
826                           uint16 smb_flags2,
827                           char **ppdest,
828                           const void *src,
829                           size_t src_len,
830                           int flags)
831 {
832         if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
833                 smb_panic("No base ptr to get flg2 and neither ASCII nor "
834                           "UNICODE defined");
835         }
836
837         if (!(flags & STR_ASCII) && \
838             ((flags & STR_UNICODE || \
839               (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
840                 return pull_ucs2_base_talloc(ctx,
841                                         base_ptr,
842                                         ppdest,
843                                         src,
844                                         src_len,
845                                         flags);
846         }
847         return pull_ascii_base_talloc(ctx,
848                                         ppdest,
849                                         src,
850                                         src_len,
851                                         flags);
852 }
853
854
855 size_t align_string(const void *base_ptr, const char *p, int flags)
856 {
857         if (!(flags & STR_ASCII) && \
858             ((flags & STR_UNICODE || \
859               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
860                 return ucs2_align(base_ptr, p, flags);
861         }
862         return 0;
863 }
864
865 /*******************************************************************
866  Write a string in (little-endian) unicode format. src is in
867  the current DOS codepage. len is the length in bytes of the
868  string pointed to by dst.
869
870  if null_terminate is True then null terminate the packet (adds 2 bytes)
871
872  the return value is the length in bytes consumed by the string, including the
873  null termination if applied
874 ********************************************************************/
875
876 size_t dos_PutUniCode(char *dst,const char *src, size_t len, bool null_terminate)
877 {
878         int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
879                                    : STR_UNICODE|STR_NOALIGN;
880         return push_ucs2(NULL, dst, src, len, flags);
881 }
882
883
884 /* Converts a string from internal samba format to unicode
885  */
886
887 int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags)
888 {
889         return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
890 }
891
892 /* Converts a string from internal samba format to unicode. Always terminates.
893  * Actually just a wrapper round push_ucs2_talloc().
894  */
895
896 int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
897 {
898         size_t size;
899         if (push_ucs2_talloc(ctx, dest, src, &size))
900                 return size;
901         else
902                 return -1;
903 }