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");
64 if (!strupper_m(tmpbuf
)) {
71 if (flags
& (STR_TERMINATE
| STR_TERMINATE_ASCII
)) {
75 ret
= convert_string(CH_UNIX
, CH_DOS
, src
, src_len
, dest
, dest_len
, &size
);
77 (flags
& (STR_TERMINATE
| STR_TERMINATE_ASCII
))
79 ((char *)dest
)[0] = '\0';
82 return ret
? size
: (size_t)-1;
85 /********************************************************************
86 Push and malloc an ascii string. src and dest null terminated.
87 ********************************************************************/
90 * Copy a string from a dos codepage source to a unix char* destination.
92 * The resulting string in "dest" is always null terminated.
94 * @param flags can have:
96 * <dt>STR_TERMINATE</dt>
97 * <dd>STR_TERMINATE means the string in @p src
98 * is null terminated, and src_len is ignored.</dd>
101 * @param src_len is the length of the source area in bytes.
102 * @returns the number of bytes occupied by the string in @p src.
104 size_t pull_ascii(char *dest
, const void *src
, size_t dest_len
, size_t src_len
, int flags
)
109 if (dest_len
== (size_t)-1) {
110 /* No longer allow dest_len of -1. */
111 smb_panic("pull_ascii - invalid dest_len of -1");
114 if (flags
& STR_TERMINATE
) {
115 if (src_len
== (size_t)-1) {
116 src_len
= strlen((const char *)src
) + 1;
118 size_t len
= strnlen((const char *)src
, src_len
);
125 ret
= convert_string(CH_DOS
, CH_UNIX
, src
, src_len
, dest
, dest_len
, &size
);
131 if (dest_len
&& size
) {
132 /* Did we already process the terminating zero ? */
133 if (dest
[MIN(size
-1, dest_len
-1)] != 0) {
134 dest
[MIN(size
, dest_len
-1)] = 0;
144 * Copy a string from a dos codepage source to a unix char* destination.
147 * The resulting string in "dest" is always null terminated.
149 * @param flags can have:
151 * <dt>STR_TERMINATE</dt>
152 * <dd>STR_TERMINATE means the string in @p src
153 * is null terminated, and src_len is ignored.</dd>
156 * @param src_len is the length of the source area in bytes.
157 * @returns the number of bytes occupied by the string in @p src.
160 static size_t pull_ascii_base_talloc(TALLOC_CTX
*ctx
,
175 if (src_len
== (size_t)-1) {
176 smb_panic("sec_len == -1 in pull_ascii_base_talloc");
179 if (flags
& STR_TERMINATE
) {
180 size_t len
= strnlen((const char *)src
, src_len
);
184 /* Ensure we don't use an insane length from the client. */
185 if (src_len
>= 1024*1024) {
186 char *msg
= talloc_asprintf(ctx
,
187 "Bad src length (%u) in "
188 "pull_ascii_base_talloc",
189 (unsigned int)src_len
);
194 /* src_len != -1 here. */
196 if (!convert_string_talloc(ctx
, CH_DOS
, CH_UNIX
, src
, src_len
, &dest
,
201 if (dest_len
&& dest
) {
202 /* Did we already process the terminating zero ? */
203 if (dest
[dest_len
-1] != 0) {
204 size_t size
= talloc_get_size(dest
);
205 /* Have we got space to append the '\0' ? */
206 if (size
<= dest_len
) {
208 dest
= talloc_realloc(ctx
, dest
, char,
212 dest_len
= (size_t)-1;
217 dest
[dest_len
] = '\0';
229 * Copy a string from a char* src to a unicode destination.
231 * @returns the number of bytes occupied by the string in the destination.
233 * @param flags can have:
236 * <dt>STR_TERMINATE <dd>means include the null termination.
237 * <dt>STR_UPPER <dd>means uppercase in the destination.
238 * <dt>STR_NOALIGN <dd>means don't do alignment.
241 * @param dest_len is the maximum length allowed in the
245 static size_t push_ucs2(const void *base_ptr
, void *dest
, const char *src
, size_t dest_len
, int flags
)
252 if (dest_len
== (size_t)-1) {
253 /* No longer allow dest_len of -1. */
254 smb_panic("push_ucs2 - invalid dest_len of -1");
257 if (flags
& STR_TERMINATE
)
258 src_len
= (size_t)-1;
260 src_len
= strlen(src
);
262 if (ucs2_align(base_ptr
, dest
, flags
)) {
264 dest
= (void *)((char *)dest
+ 1);
270 /* ucs2 is always a multiple of 2 bytes */
273 ret
= convert_string(CH_UNIX
, CH_UTF16LE
, src
, src_len
, dest
, dest_len
, &size
);
275 if ((flags
& STR_TERMINATE
) &&
285 if (flags
& STR_UPPER
) {
286 smb_ucs2_t
*dest_ucs2
= (smb_ucs2_t
*)dest
;
289 /* We check for i < (ret / 2) below as the dest string isn't null
290 terminated if STR_TERMINATE isn't set. */
292 for (i
= 0; i
< (ret
/ 2) && i
< (dest_len
/ 2) && dest_ucs2
[i
]; i
++) {
293 smb_ucs2_t v
= toupper_w(dest_ucs2
[i
]);
294 if (v
!= dest_ucs2
[i
]) {
304 Copy a string from a ucs2 source to a unix char* destination.
305 Talloc version with a base pointer.
306 Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
309 STR_TERMINATE means the string in src is null terminated.
310 STR_NOALIGN means don't try to align.
311 if STR_TERMINATE is set then src_len is ignored if it is -1.
312 src_len is the length of the source area in bytes
313 Return the number of bytes occupied by the string in src.
314 The resulting string in "dest" is always null terminated.
317 static size_t pull_ucs2_base_talloc(TALLOC_CTX
*ctx
,
318 const void *base_ptr
,
326 size_t ucs2_align_len
= 0;
331 /* Ensure we never use the braindead "malloc" varient. */
333 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
341 if (src_len
== (size_t)-1) {
342 /* no longer used anywhere, but worth checking */
343 smb_panic("sec_len == -1 in pull_ucs2_base_talloc");
346 if (ucs2_align(base_ptr
, src
, flags
)) {
347 src
= (const void *)((const char *)src
+ 1);
352 if (flags
& STR_TERMINATE
) {
353 /* src_len -1 is the default for null terminated strings. */
354 size_t len
= strnlen_w((const smb_ucs2_t
*)src
,
360 /* Ensure we don't use an insane length from the client. */
361 if (src_len
>= 1024*1024) {
362 smb_panic("Bad src length in pull_ucs2_base_talloc\n");
366 /* ucs2 is always a multiple of 2 bytes */
369 if (!convert_string_talloc(ctx
, CH_UTF16LE
, CH_UNIX
, src
, src_len
,
370 (void *)&dest
, &dest_len
)) {
375 /* Did we already process the terminating zero ? */
376 if (dest
[dest_len
-1] != 0) {
377 size_t size
= talloc_get_size(dest
);
378 /* Have we got space to append the '\0' ? */
379 if (size
<= dest_len
) {
381 dest
= talloc_realloc(ctx
, dest
, char,
385 dest_len
= (size_t)-1;
390 dest
[dest_len
] = '\0';
398 return src_len
+ ucs2_align_len
;
402 Copy a string from a char* src to a unicode or ascii
403 dos codepage destination choosing unicode or ascii based on the
405 Return the number of bytes occupied by the string in the destination.
407 STR_TERMINATE means include the null termination.
408 STR_UPPER means uppercase in the destination.
409 STR_ASCII use ascii even with unicode packet.
410 STR_NOALIGN means don't do alignment.
411 dest_len is the maximum length allowed in the destination. If dest_len
412 is -1 then no maxiumum is used.
415 size_t push_string_check_fn(void *dest
, const char *src
,
416 size_t dest_len
, int flags
)
418 if (!(flags
& STR_ASCII
) && (flags
& STR_UNICODE
)) {
419 return push_ucs2(NULL
, dest
, src
, dest_len
, flags
);
421 return push_ascii(dest
, src
, dest_len
, flags
);
426 Copy a string from a char* src to a unicode or ascii
427 dos codepage destination choosing unicode or ascii based on the
428 flags in the SMB buffer starting at base_ptr.
429 Return the number of bytes occupied by the string in the destination.
431 STR_TERMINATE means include the null termination.
432 STR_UPPER means uppercase in the destination.
433 STR_ASCII use ascii even with unicode packet.
434 STR_NOALIGN means don't do alignment.
435 dest_len is the maximum length allowed in the destination. If dest_len
436 is -1 then no maxiumum is used.
439 size_t push_string_base(const char *base
, uint16 flags2
,
440 void *dest
, const char *src
,
441 size_t dest_len
, int flags
)
444 if (!(flags
& STR_ASCII
) && \
445 ((flags
& STR_UNICODE
|| \
446 (flags2
& FLAGS2_UNICODE_STRINGS
)))) {
447 return push_ucs2(base
, dest
, src
, dest_len
, flags
);
449 return push_ascii(dest
, src
, dest_len
, flags
);
453 Copy a string from a unicode or ascii source (depending on
454 the packet flags) to a char* destination.
455 Variant that uses talloc.
457 STR_TERMINATE means the string in src is null terminated.
458 STR_UNICODE means to force as unicode.
459 STR_ASCII use ascii even with unicode packet.
460 STR_NOALIGN means don't do alignment.
461 if STR_TERMINATE is set then src_len is ignored is it is -1
462 src_len is the length of the source area in bytes.
463 Return the number of bytes occupied by the string in src.
464 The resulting string in "dest" is always null terminated.
467 size_t pull_string_talloc(TALLOC_CTX
*ctx
,
468 const void *base_ptr
,
475 if ((base_ptr
== NULL
) && ((flags
& (STR_ASCII
|STR_UNICODE
)) == 0)) {
476 smb_panic("No base ptr to get flg2 and neither ASCII nor "
480 if (!(flags
& STR_ASCII
) && \
481 ((flags
& STR_UNICODE
|| \
482 (smb_flags2
& FLAGS2_UNICODE_STRINGS
)))) {
483 return pull_ucs2_base_talloc(ctx
,
490 return pull_ascii_base_talloc(ctx
,
498 size_t align_string(const void *base_ptr
, const char *p
, int flags
)
500 if (!(flags
& STR_ASCII
) && \
501 ((flags
& STR_UNICODE
|| \
502 (SVAL(base_ptr
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
)))) {
503 return ucs2_align(base_ptr
, p
, flags
);
508 /*******************************************************************
509 Write a string in (little-endian) unicode format. src is in
510 the current DOS codepage. len is the length in bytes of the
511 string pointed to by dst.
513 if null_terminate is True then null terminate the packet (adds 2 bytes)
515 the return value is the length in bytes consumed by the string, including the
516 null termination if applied
517 ********************************************************************/
519 size_t dos_PutUniCode(char *dst
,const char *src
, size_t len
, bool null_terminate
)
521 int flags
= null_terminate
? STR_UNICODE
|STR_NOALIGN
|STR_TERMINATE
522 : STR_UNICODE
|STR_NOALIGN
;
523 return push_ucs2(NULL
, dst
, src
, len
, flags
);
527 /* Converts a string from internal samba format to unicode. Always terminates.
528 * Actually just a wrapper round push_ucs2_talloc().
531 int rpcstr_push_talloc(TALLOC_CTX
*ctx
, smb_ucs2_t
**dest
, const char *src
)
534 if (push_ucs2_talloc(ctx
, dest
, src
, &size
))