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
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.
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.
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/>.
26 * Destroy global objects allocated by init_iconv()
28 void gfree_charcnv(void)
30 TALLOC_FREE(global_iconv_handle
);
34 * Copy a string from a char* unix src to a dos codepage string destination.
36 * @return the number of bytes occupied by the string in the destination.
38 * @param flags can include
40 * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
41 * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
44 * @param dest_len the maximum length in bytes allowed in the
47 size_t push_ascii(void *dest
, const char *src
, size_t dest_len
, int flags
)
49 size_t src_len
= strlen(src
);
54 /* No longer allow a length of -1. */
55 if (dest_len
== (size_t)-1) {
56 smb_panic("push_ascii - dest_len == -1");
59 if (flags
& STR_UPPER
) {
60 tmpbuf
= SMB_STRDUP(src
);
62 smb_panic("malloc fail");
68 if (flags
& (STR_TERMINATE
| STR_TERMINATE_ASCII
)) {
72 ret
= convert_string(CH_UNIX
, CH_DOS
, src
, src_len
, dest
, dest_len
, &size
);
74 (flags
& (STR_TERMINATE
| STR_TERMINATE_ASCII
))
76 ((char *)dest
)[0] = '\0';
79 return ret
? size
: (size_t)-1;
82 /********************************************************************
83 Push and malloc an ascii string. src and dest null terminated.
84 ********************************************************************/
87 * Copy a string from a dos codepage source to a unix char* destination.
89 * The resulting string in "dest" is always null terminated.
91 * @param flags can have:
93 * <dt>STR_TERMINATE</dt>
94 * <dd>STR_TERMINATE means the string in @p src
95 * is null terminated, and src_len is ignored.</dd>
98 * @param src_len is the length of the source area in bytes.
99 * @returns the number of bytes occupied by the string in @p src.
101 size_t pull_ascii(char *dest
, const void *src
, size_t dest_len
, size_t src_len
, int flags
)
106 if (dest_len
== (size_t)-1) {
107 /* No longer allow dest_len of -1. */
108 smb_panic("pull_ascii - invalid dest_len of -1");
111 if (flags
& STR_TERMINATE
) {
112 if (src_len
== (size_t)-1) {
113 src_len
= strlen((const char *)src
) + 1;
115 size_t len
= strnlen((const char *)src
, src_len
);
122 ret
= convert_string(CH_DOS
, CH_UNIX
, src
, src_len
, dest
, dest_len
, &size
);
128 if (dest_len
&& size
) {
129 /* Did we already process the terminating zero ? */
130 if (dest
[MIN(size
-1, dest_len
-1)] != 0) {
131 dest
[MIN(size
, dest_len
-1)] = 0;
141 * Copy a string from a dos codepage source to a unix char* destination.
144 * The resulting string in "dest" is always null terminated.
146 * @param flags can have:
148 * <dt>STR_TERMINATE</dt>
149 * <dd>STR_TERMINATE means the string in @p src
150 * is null terminated, and src_len is ignored.</dd>
153 * @param src_len is the length of the source area in bytes.
154 * @returns the number of bytes occupied by the string in @p src.
157 static size_t pull_ascii_base_talloc(TALLOC_CTX
*ctx
,
172 if (src_len
== (size_t)-1) {
173 smb_panic("sec_len == -1 in pull_ascii_base_talloc");
176 if (flags
& STR_TERMINATE
) {
177 size_t len
= strnlen((const char *)src
, src_len
);
181 /* Ensure we don't use an insane length from the client. */
182 if (src_len
>= 1024*1024) {
183 char *msg
= talloc_asprintf(ctx
,
184 "Bad src length (%u) in "
185 "pull_ascii_base_talloc",
186 (unsigned int)src_len
);
191 /* src_len != -1 here. */
193 if (!convert_string_talloc(ctx
, CH_DOS
, CH_UNIX
, src
, src_len
, &dest
,
198 if (dest_len
&& dest
) {
199 /* Did we already process the terminating zero ? */
200 if (dest
[dest_len
-1] != 0) {
201 size_t size
= talloc_get_size(dest
);
202 /* Have we got space to append the '\0' ? */
203 if (size
<= dest_len
) {
205 dest
= talloc_realloc(ctx
, dest
, char,
209 dest_len
= (size_t)-1;
214 dest
[dest_len
] = '\0';
226 * Copy a string from a char* src to a unicode destination.
228 * @returns the number of bytes occupied by the string in the destination.
230 * @param flags can have:
233 * <dt>STR_TERMINATE <dd>means include the null termination.
234 * <dt>STR_UPPER <dd>means uppercase in the destination.
235 * <dt>STR_NOALIGN <dd>means don't do alignment.
238 * @param dest_len is the maximum length allowed in the
242 static size_t push_ucs2(const void *base_ptr
, void *dest
, const char *src
, size_t dest_len
, int flags
)
249 if (dest_len
== (size_t)-1) {
250 /* No longer allow dest_len of -1. */
251 smb_panic("push_ucs2 - invalid dest_len of -1");
254 if (flags
& STR_TERMINATE
)
255 src_len
= (size_t)-1;
257 src_len
= strlen(src
);
259 if (ucs2_align(base_ptr
, dest
, flags
)) {
261 dest
= (void *)((char *)dest
+ 1);
267 /* ucs2 is always a multiple of 2 bytes */
270 ret
= convert_string(CH_UNIX
, CH_UTF16LE
, src
, src_len
, dest
, dest_len
, &size
);
272 if ((flags
& STR_TERMINATE
) &&
282 if (flags
& STR_UPPER
) {
283 smb_ucs2_t
*dest_ucs2
= (smb_ucs2_t
*)dest
;
286 /* We check for i < (ret / 2) below as the dest string isn't null
287 terminated if STR_TERMINATE isn't set. */
289 for (i
= 0; i
< (ret
/ 2) && i
< (dest_len
/ 2) && dest_ucs2
[i
]; i
++) {
290 smb_ucs2_t v
= toupper_w(dest_ucs2
[i
]);
291 if (v
!= dest_ucs2
[i
]) {
303 Copy a string from a ucs2 source to a unix char* destination.
305 STR_TERMINATE means the string in src is null terminated.
306 STR_NOALIGN means don't try to align.
307 if STR_TERMINATE is set then src_len is ignored if it is -1.
308 src_len is the length of the source area in bytes
309 Return the number of bytes occupied by the string in src.
310 The resulting string in "dest" is always null terminated.
313 static size_t pull_ucs2(const void *base_ptr
, char *dest
, const void *src
, size_t dest_len
, size_t src_len
, int flags
)
316 size_t ucs2_align_len
= 0;
319 if (dest_len
== (size_t)-1) {
320 /* No longer allow dest_len of -1. */
321 smb_panic("pull_ucs2 - invalid dest_len of -1");
325 if (dest
&& dest_len
> 0) {
331 if (ucs2_align(base_ptr
, src
, flags
)) {
332 src
= (const void *)((const char *)src
+ 1);
333 if (src_len
!= (size_t)-1)
338 if (flags
& STR_TERMINATE
) {
339 /* src_len -1 is the default for null terminated strings. */
340 if (src_len
!= (size_t)-1) {
341 size_t len
= strnlen_w((const smb_ucs2_t
*)src
,
349 /* ucs2 is always a multiple of 2 bytes */
350 if (src_len
!= (size_t)-1)
353 ret
= convert_string(CH_UTF16LE
, CH_UNIX
, src
, src_len
, dest
, dest_len
, &size
);
359 if (src_len
== (size_t)-1)
362 if (dest_len
&& size
) {
363 /* Did we already process the terminating zero ? */
364 if (dest
[MIN(size
-1, dest_len
-1)] != 0) {
365 dest
[MIN(size
, dest_len
-1)] = 0;
371 return src_len
+ ucs2_align_len
;
375 Copy a string from a ucs2 source to a unix char* destination.
376 Talloc version with a base pointer.
377 Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
380 STR_TERMINATE means the string in src is null terminated.
381 STR_NOALIGN means don't try to align.
382 if STR_TERMINATE is set then src_len is ignored if it is -1.
383 src_len is the length of the source area in bytes
384 Return the number of bytes occupied by the string in src.
385 The resulting string in "dest" is always null terminated.
388 static size_t pull_ucs2_base_talloc(TALLOC_CTX
*ctx
,
389 const void *base_ptr
,
397 size_t ucs2_align_len
= 0;
402 /* Ensure we never use the braindead "malloc" varient. */
404 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
412 if (src_len
== (size_t)-1) {
413 /* no longer used anywhere, but worth checking */
414 smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
417 if (ucs2_align(base_ptr
, src
, flags
)) {
418 src
= (const void *)((const char *)src
+ 1);
423 if (flags
& STR_TERMINATE
) {
424 /* src_len -1 is the default for null terminated strings. */
425 size_t len
= strnlen_w((const smb_ucs2_t
*)src
,
431 /* Ensure we don't use an insane length from the client. */
432 if (src_len
>= 1024*1024) {
433 smb_panic("Bad src length in pull_ucs2_base_talloc\n");
437 /* ucs2 is always a multiple of 2 bytes */
440 if (!convert_string_talloc(ctx
, CH_UTF16LE
, CH_UNIX
, src
, src_len
,
441 (void *)&dest
, &dest_len
)) {
446 /* Did we already process the terminating zero ? */
447 if (dest
[dest_len
-1] != 0) {
448 size_t size
= talloc_get_size(dest
);
449 /* Have we got space to append the '\0' ? */
450 if (size
<= dest_len
) {
452 dest
= talloc_realloc(ctx
, dest
, char,
456 dest_len
= (size_t)-1;
461 dest
[dest_len
] = '\0';
469 return src_len
+ ucs2_align_len
;
473 Copy a string from a char* src to a unicode or ascii
474 dos codepage destination choosing unicode or ascii based on the
476 Return the number of bytes occupied by the string in the destination.
478 STR_TERMINATE means include the null termination.
479 STR_UPPER means uppercase in the destination.
480 STR_ASCII use ascii even with unicode packet.
481 STR_NOALIGN means don't do alignment.
482 dest_len is the maximum length allowed in the destination. If dest_len
483 is -1 then no maxiumum is used.
486 size_t push_string_check_fn(void *dest
, const char *src
,
487 size_t dest_len
, int flags
)
489 if (!(flags
& STR_ASCII
) && (flags
& STR_UNICODE
)) {
490 return push_ucs2(NULL
, dest
, src
, dest_len
, flags
);
492 return push_ascii(dest
, src
, dest_len
, flags
);
497 Copy a string from a char* src to a unicode or ascii
498 dos codepage destination choosing unicode or ascii based on the
499 flags in the SMB buffer starting at base_ptr.
500 Return the number of bytes occupied by the string in the destination.
502 STR_TERMINATE means include the null termination.
503 STR_UPPER means uppercase in the destination.
504 STR_ASCII use ascii even with unicode packet.
505 STR_NOALIGN means don't do alignment.
506 dest_len is the maximum length allowed in the destination. If dest_len
507 is -1 then no maxiumum is used.
510 size_t push_string_base(const char *base
, uint16 flags2
,
511 void *dest
, const char *src
,
512 size_t dest_len
, int flags
)
515 if (!(flags
& STR_ASCII
) && \
516 ((flags
& STR_UNICODE
|| \
517 (flags2
& FLAGS2_UNICODE_STRINGS
)))) {
518 return push_ucs2(base
, dest
, src
, dest_len
, flags
);
520 return push_ascii(dest
, src
, dest_len
, flags
);
524 Copy a string from a unicode or ascii source (depending on
525 the packet flags) to a char* destination.
527 STR_TERMINATE means the string in src is null terminated.
528 STR_UNICODE means to force as unicode.
529 STR_ASCII use ascii even with unicode packet.
530 STR_NOALIGN means don't do alignment.
531 if STR_TERMINATE is set then src_len is ignored is it is -1
532 src_len is the length of the source area in bytes.
533 Return the number of bytes occupied by the string in src.
534 The resulting string in "dest" is always null terminated.
537 size_t pull_string_fn(const void *base_ptr
,
545 if ((base_ptr
== NULL
) && ((flags
& (STR_ASCII
|STR_UNICODE
)) == 0)) {
546 smb_panic("No base ptr to get flg2 and neither ASCII nor "
550 if (!(flags
& STR_ASCII
) && \
551 ((flags
& STR_UNICODE
|| \
552 (smb_flags2
& FLAGS2_UNICODE_STRINGS
)))) {
553 return pull_ucs2(base_ptr
, dest
, src
, dest_len
, src_len
, flags
);
555 return pull_ascii(dest
, src
, dest_len
, src_len
, flags
);
559 Copy a string from a unicode or ascii source (depending on
560 the packet flags) to a char* destination.
561 Variant that uses talloc.
563 STR_TERMINATE means the string in src is null terminated.
564 STR_UNICODE means to force as unicode.
565 STR_ASCII use ascii even with unicode packet.
566 STR_NOALIGN means don't do alignment.
567 if STR_TERMINATE is set then src_len is ignored is it is -1
568 src_len is the length of the source area in bytes.
569 Return the number of bytes occupied by the string in src.
570 The resulting string in "dest" is always null terminated.
573 size_t pull_string_talloc(TALLOC_CTX
*ctx
,
574 const void *base_ptr
,
581 if ((base_ptr
== NULL
) && ((flags
& (STR_ASCII
|STR_UNICODE
)) == 0)) {
582 smb_panic("No base ptr to get flg2 and neither ASCII nor "
586 if (!(flags
& STR_ASCII
) && \
587 ((flags
& STR_UNICODE
|| \
588 (smb_flags2
& FLAGS2_UNICODE_STRINGS
)))) {
589 return pull_ucs2_base_talloc(ctx
,
596 return pull_ascii_base_talloc(ctx
,
604 size_t align_string(const void *base_ptr
, const char *p
, int flags
)
606 if (!(flags
& STR_ASCII
) && \
607 ((flags
& STR_UNICODE
|| \
608 (SVAL(base_ptr
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
)))) {
609 return ucs2_align(base_ptr
, p
, flags
);
614 /*******************************************************************
615 Write a string in (little-endian) unicode format. src is in
616 the current DOS codepage. len is the length in bytes of the
617 string pointed to by dst.
619 if null_terminate is True then null terminate the packet (adds 2 bytes)
621 the return value is the length in bytes consumed by the string, including the
622 null termination if applied
623 ********************************************************************/
625 size_t dos_PutUniCode(char *dst
,const char *src
, size_t len
, bool null_terminate
)
627 int flags
= null_terminate
? STR_UNICODE
|STR_NOALIGN
|STR_TERMINATE
628 : STR_UNICODE
|STR_NOALIGN
;
629 return push_ucs2(NULL
, dst
, src
, len
, flags
);
633 /* Converts a string from internal samba format to unicode
636 int rpcstr_push(void *dest
, const char *src
, size_t dest_len
, int flags
)
638 return push_ucs2(NULL
, dest
, src
, dest_len
, flags
|STR_UNICODE
|STR_NOALIGN
);
641 /* Converts a string from internal samba format to unicode. Always terminates.
642 * Actually just a wrapper round push_ucs2_talloc().
645 int rpcstr_push_talloc(TALLOC_CTX
*ctx
, smb_ucs2_t
**dest
, const char *src
)
648 if (push_ucs2_talloc(ctx
, dest
, src
, &size
))