Merge tag 'samba-4.0.13' into v4-0-test
[Samba.git] / source3 / lib / charcnv.c
blob1fa2c5c8cfc5c1df2cd1ff3e73cb9e9a14d78532
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
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/>.
23 #include "includes.h"
25 /**
26 * Destroy global objects allocated by init_iconv()
27 **/
28 void gfree_charcnv(void)
30 TALLOC_FREE(global_iconv_handle);
33 /**
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
39 * <dl>
40 * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
41 * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
42 * </dl>
44 * @param dest_len the maximum length in bytes allowed in the
45 * destination.
46 **/
47 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
49 size_t src_len = strlen(src);
50 char *tmpbuf = NULL;
51 size_t size;
52 bool ret;
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);
61 if (!tmpbuf) {
62 smb_panic("malloc fail");
64 if (!strupper_m(tmpbuf)) {
65 SAFE_FREE(tmpbuf);
66 return (size_t)-1;
68 src = tmpbuf;
71 if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) {
72 src_len++;
75 ret = convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, &size);
76 if (ret == false &&
77 (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
78 && dest_len > 0) {
79 ((char *)dest)[0] = '\0';
81 SAFE_FREE(tmpbuf);
82 return ret ? size : (size_t)-1;
85 /********************************************************************
86 Push and malloc an ascii string. src and dest null terminated.
87 ********************************************************************/
89 /**
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:
95 * <dl>
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>
99 * </dl>
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)
106 bool ret;
107 size_t size = 0;
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;
117 } else {
118 size_t len = strnlen((const char *)src, src_len);
119 if (len < src_len)
120 len++;
121 src_len = len;
125 ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len, &size);
126 if (ret == false) {
127 size = 0;
128 dest_len = 0;
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;
136 } else {
137 dest[0] = 0;
140 return src_len;
144 * Copy a string from a dos codepage source to a unix char* destination.
145 * Talloc version.
147 * The resulting string in "dest" is always null terminated.
149 * @param flags can have:
150 * <dl>
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>
154 * </dl>
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,
161 char **ppdest,
162 const void *src,
163 size_t src_len,
164 int flags)
166 char *dest = NULL;
167 size_t dest_len;
169 *ppdest = NULL;
171 if (!src_len) {
172 return 0;
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);
181 if (len < src_len)
182 len++;
183 src_len = 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);
190 smb_panic(msg);
194 /* src_len != -1 here. */
196 if (!convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, &dest,
197 &dest_len)) {
198 dest_len = 0;
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) {
207 /* No, realloc. */
208 dest = talloc_realloc(ctx, dest, char,
209 dest_len+1);
210 if (!dest) {
211 /* talloc fail. */
212 dest_len = (size_t)-1;
213 return 0;
216 /* Yay - space ! */
217 dest[dest_len] = '\0';
218 dest_len++;
220 } else if (dest) {
221 dest[0] = 0;
224 *ppdest = dest;
225 return src_len;
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:
235 * <dl>
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.
239 * </dl>
241 * @param dest_len is the maximum length allowed in the
242 * destination.
245 static size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
247 size_t len=0;
248 size_t src_len;
249 size_t size = 0;
250 bool ret;
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;
259 else
260 src_len = strlen(src);
262 if (ucs2_align(base_ptr, dest, flags)) {
263 *(char *)dest = 0;
264 dest = (void *)((char *)dest + 1);
265 if (dest_len)
266 dest_len--;
267 len++;
270 /* ucs2 is always a multiple of 2 bytes */
271 dest_len &= ~1;
273 ret = convert_string(CH_UNIX, CH_UTF16LE, src, src_len, dest, dest_len, &size);
274 if (ret == false) {
275 if ((flags & STR_TERMINATE) &&
276 dest &&
277 dest_len) {
278 *(char *)dest = 0;
280 return len;
283 len += size;
285 if (flags & STR_UPPER) {
286 smb_ucs2_t *dest_ucs2 = (smb_ucs2_t *)dest;
287 size_t i;
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]) {
295 dest_ucs2[i] = v;
300 return len;
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
307 needs fixing. JRA).
308 Flags can have:
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,
319 char **ppdest,
320 const void *src,
321 size_t src_len,
322 int flags)
324 char *dest;
325 size_t dest_len;
326 size_t ucs2_align_len = 0;
328 *ppdest = NULL;
330 #ifdef DEVELOPER
331 /* Ensure we never use the braindead "malloc" varient. */
332 if (ctx == NULL) {
333 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
335 #endif
337 if (!src_len) {
338 return 0;
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);
348 src_len--;
349 ucs2_align_len = 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,
355 src_len/2);
356 if (len < src_len/2)
357 len++;
358 src_len = len*2;
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 */
367 src_len &= ~1;
369 if (!convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX, src, src_len,
370 (void *)&dest, &dest_len)) {
371 dest_len = 0;
374 if (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) {
380 /* No, realloc. */
381 dest = talloc_realloc(ctx, dest, char,
382 dest_len+1);
383 if (!dest) {
384 /* talloc fail. */
385 dest_len = (size_t)-1;
386 return 0;
389 /* Yay - space ! */
390 dest[dest_len] = '\0';
391 dest_len++;
393 } else if (dest) {
394 dest[0] = 0;
397 *ppdest = dest;
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
404 flags supplied
405 Return the number of bytes occupied by the string in the destination.
406 flags can have:
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.
430 flags can have:
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.
456 Flags can have:
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,
469 uint16 smb_flags2,
470 char **ppdest,
471 const void *src,
472 size_t src_len,
473 int flags)
475 if ((base_ptr == NULL) && ((flags & (STR_ASCII|STR_UNICODE)) == 0)) {
476 smb_panic("No base ptr to get flg2 and neither ASCII nor "
477 "UNICODE defined");
480 if (!(flags & STR_ASCII) && \
481 ((flags & STR_UNICODE || \
482 (smb_flags2 & FLAGS2_UNICODE_STRINGS)))) {
483 return pull_ucs2_base_talloc(ctx,
484 base_ptr,
485 ppdest,
486 src,
487 src_len,
488 flags);
490 return pull_ascii_base_talloc(ctx,
491 ppdest,
492 src,
493 src_len,
494 flags);
497 /*******************************************************************
498 Write a string in (little-endian) unicode format. src is in
499 the current DOS codepage. len is the length in bytes of the
500 string pointed to by dst.
502 if null_terminate is True then null terminate the packet (adds 2 bytes)
504 the return value is the length in bytes consumed by the string, including the
505 null termination if applied
506 ********************************************************************/
508 size_t dos_PutUniCode(char *dst,const char *src, size_t len, bool null_terminate)
510 int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
511 : STR_UNICODE|STR_NOALIGN;
512 return push_ucs2(NULL, dst, src, len, flags);
516 /* Converts a string from internal samba format to unicode. Always terminates.
517 * Actually just a wrapper round push_ucs2_talloc().
520 int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
522 size_t size;
523 if (push_ucs2_talloc(ctx, dest, src, &size))
524 return size;
525 else
526 return -1;