1 /*
2 * UTF-7 stream functions
3 *
4 * Copyright (C) 2008-2020, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <memory.h>
24 #include <types.h>
25
26 #include "libuna_definitions.h"
27 #include "libuna_libcerror.h"
28 #include "libuna_types.h"
29 #include "libuna_unicode_character.h"
30 #include "libuna_utf7_stream.h"
31
32 /* Determines the size of an UTF-7 stream from an UTF-8 string
33 * Returns 1 if successful or -1 on error
34 */
libuna_utf7_stream_size_from_utf8(const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,size_t * utf7_stream_size,libcerror_error_t ** error)35 int libuna_utf7_stream_size_from_utf8(
36 const libuna_utf8_character_t *utf8_string,
37 size_t utf8_string_size,
38 size_t *utf7_stream_size,
39 libcerror_error_t **error )
40 {
41 static char *function = "libuna_utf7_stream_size_from_utf8";
42 libuna_unicode_character_t unicode_character = 0;
43 size_t utf8_string_index = 0;
44 uint32_t utf7_stream_base64_data = 0;
45
46 if( utf8_string == NULL )
47 {
48 libcerror_error_set(
49 error,
50 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52 "%s: invalid UTF-8 string.",
53 function );
54
55 return( -1 );
56 }
57 if( utf8_string_size > (size_t) SSIZE_MAX )
58 {
59 libcerror_error_set(
60 error,
61 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
63 "%s: invalid UTF-8 string size value exceeds maximum.",
64 function );
65
66 return( -1 );
67 }
68 if( utf7_stream_size == NULL )
69 {
70 libcerror_error_set(
71 error,
72 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
73 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
74 "%s: invalid UTF-7 stream size.",
75 function );
76
77 return( -1 );
78 }
79 while( utf8_string_index < utf8_string_size )
80 {
81 /* Convert the UTF-8 character bytes into an Unicode character
82 */
83 if( libuna_unicode_character_copy_from_utf8(
84 &unicode_character,
85 utf8_string,
86 utf8_string_size,
87 &utf8_string_index,
88 error ) != 1 )
89 {
90 libcerror_error_set(
91 error,
92 LIBCERROR_ERROR_DOMAIN_CONVERSION,
93 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
94 "%s: unable to copy Unicode character from UTF-8.",
95 function );
96
97 return( -1 );
98 }
99 /* Determine how many UTF-7 character bytes are required
100 */
101 if( libuna_unicode_character_size_to_utf7_stream(
102 unicode_character,
103 utf7_stream_size,
104 &utf7_stream_base64_data,
105 error ) != 1 )
106 {
107 libcerror_error_set(
108 error,
109 LIBCERROR_ERROR_DOMAIN_CONVERSION,
110 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
111 "%s: unable to determine size of Unicode character in UTF-7.",
112 function );
113
114 return( -1 );
115 }
116 if( unicode_character == 0 )
117 {
118 break;
119 }
120 }
121 return( 1 );
122 }
123
124 /* Copies an UTF-7 stream from an UTF-8 string
125 * Returns 1 if successful or -1 on error
126 */
libuna_utf7_stream_copy_from_utf8(uint8_t * utf7_stream,size_t utf7_stream_size,const libuna_utf8_character_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)127 int libuna_utf7_stream_copy_from_utf8(
128 uint8_t *utf7_stream,
129 size_t utf7_stream_size,
130 const libuna_utf8_character_t *utf8_string,
131 size_t utf8_string_size,
132 libcerror_error_t **error )
133 {
134 static char *function = "libuna_utf7_stream_copy_from_utf8";
135 libuna_unicode_character_t unicode_character = 0;
136 size_t utf7_stream_index = 0;
137 size_t utf8_string_index = 0;
138 uint32_t utf7_stream_base64_data = 0;
139
140 if( utf7_stream == NULL )
141 {
142 libcerror_error_set(
143 error,
144 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
145 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
146 "%s: invalid UTF-7 stream.",
147 function );
148
149 return( -1 );
150 }
151 if( utf7_stream_size > (size_t) SSIZE_MAX )
152 {
153 libcerror_error_set(
154 error,
155 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
156 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
157 "%s: invalid UTF-7 stream size value exceeds maximum.",
158 function );
159
160 return( -1 );
161 }
162 if( utf8_string == NULL )
163 {
164 libcerror_error_set(
165 error,
166 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
167 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
168 "%s: invalid UTF-8 string.",
169 function );
170
171 return( -1 );
172 }
173 if( utf8_string_size > (size_t) SSIZE_MAX )
174 {
175 libcerror_error_set(
176 error,
177 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
178 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
179 "%s: invalid UTF-8 string size value exceeds maximum.",
180 function );
181
182 return( -1 );
183 }
184 while( utf8_string_index < utf8_string_size )
185 {
186 /* Convert the UTF-8 string bytes into an Unicode character
187 */
188 if( libuna_unicode_character_copy_from_utf8(
189 &unicode_character,
190 utf8_string,
191 utf8_string_size,
192 &utf8_string_index,
193 error ) != 1 )
194 {
195 libcerror_error_set(
196 error,
197 LIBCERROR_ERROR_DOMAIN_CONVERSION,
198 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
199 "%s: unable to copy Unicode character from UTF-8 string.",
200 function );
201
202 return( -1 );
203 }
204 /* Convert the Unicode character into UTF-7 stream bytes
205 */
206 if( libuna_unicode_character_copy_to_utf7_stream(
207 unicode_character,
208 utf7_stream,
209 utf7_stream_size,
210 &utf7_stream_index,
211 &utf7_stream_base64_data,
212 error ) != 1 )
213 {
214 libcerror_error_set(
215 error,
216 LIBCERROR_ERROR_DOMAIN_CONVERSION,
217 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
218 "%s: unable to copy Unicode character to UTF-7 stream.",
219 function );
220
221 return( -1 );
222 }
223 if( unicode_character == 0 )
224 {
225 break;
226 }
227 }
228 return( 1 );
229 }
230
231 /* Determines the size of an UTF-7 stream from an UTF-16 string
232 * Returns 1 if successful or -1 on error
233 */
libuna_utf7_stream_size_from_utf16(const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,size_t * utf7_stream_size,libcerror_error_t ** error)234 int libuna_utf7_stream_size_from_utf16(
235 const libuna_utf16_character_t *utf16_string,
236 size_t utf16_string_size,
237 size_t *utf7_stream_size,
238 libcerror_error_t **error )
239 {
240 static char *function = "libuna_utf7_stream_size_from_utf16";
241 libuna_unicode_character_t unicode_character = 0;
242 size_t utf16_string_index = 0;
243 uint32_t utf7_stream_base64_data = 0;
244
245 if( utf16_string == NULL )
246 {
247 libcerror_error_set(
248 error,
249 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
250 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
251 "%s: invalid UTF-16 string.",
252 function );
253
254 return( -1 );
255 }
256 if( utf16_string_size > (size_t) SSIZE_MAX )
257 {
258 libcerror_error_set(
259 error,
260 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
261 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
262 "%s: invalid UTF-16 string size value exceeds maximum.",
263 function );
264
265 return( -1 );
266 }
267 if( utf7_stream_size == NULL )
268 {
269 libcerror_error_set(
270 error,
271 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
272 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
273 "%s: invalid UTF-7 stream size.",
274 function );
275
276 return( -1 );
277 }
278 while( utf16_string_index < utf16_string_size )
279 {
280 /* Convert the UTF-16 character bytes into an Unicode character
281 */
282 if( libuna_unicode_character_copy_from_utf16(
283 &unicode_character,
284 utf16_string,
285 utf16_string_size,
286 &utf16_string_index,
287 error ) != 1 )
288 {
289 libcerror_error_set(
290 error,
291 LIBCERROR_ERROR_DOMAIN_CONVERSION,
292 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
293 "%s: unable to copy Unicode character from UTF-16.",
294 function );
295
296 return( -1 );
297 }
298 /* Determine how many UTF-7 character bytes are required
299 */
300 if( libuna_unicode_character_size_to_utf7_stream(
301 unicode_character,
302 utf7_stream_size,
303 &utf7_stream_base64_data,
304 error ) != 1 )
305 {
306 libcerror_error_set(
307 error,
308 LIBCERROR_ERROR_DOMAIN_CONVERSION,
309 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
310 "%s: unable to determine size of Unicode character in UTF-7.",
311 function );
312
313 return( -1 );
314 }
315 if( unicode_character == 0 )
316 {
317 break;
318 }
319 }
320 return( 1 );
321 }
322
323 /* Copies an UTF-7 stream from an UTF-16 string
324 * Returns 1 if successful or -1 on error
325 */
libuna_utf7_stream_copy_from_utf16(uint8_t * utf7_stream,size_t utf7_stream_size,const libuna_utf16_character_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)326 int libuna_utf7_stream_copy_from_utf16(
327 uint8_t *utf7_stream,
328 size_t utf7_stream_size,
329 const libuna_utf16_character_t *utf16_string,
330 size_t utf16_string_size,
331 libcerror_error_t **error )
332 {
333 static char *function = "libuna_utf7_stream_copy_from_utf16";
334 libuna_unicode_character_t unicode_character = 0;
335 size_t utf16_string_index = 0;
336 size_t utf7_stream_index = 0;
337 uint32_t utf7_stream_base64_data = 0;
338
339 if( utf7_stream == NULL )
340 {
341 libcerror_error_set(
342 error,
343 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
344 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
345 "%s: invalid UTF-7 stream.",
346 function );
347
348 return( -1 );
349 }
350 if( utf7_stream_size > (size_t) SSIZE_MAX )
351 {
352 libcerror_error_set(
353 error,
354 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
355 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
356 "%s: invalid UTF-7 stream size value exceeds maximum.",
357 function );
358
359 return( -1 );
360 }
361 if( utf16_string == NULL )
362 {
363 libcerror_error_set(
364 error,
365 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
366 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
367 "%s: invalid UTF-16 string.",
368 function );
369
370 return( -1 );
371 }
372 if( utf16_string_size > (size_t) SSIZE_MAX )
373 {
374 libcerror_error_set(
375 error,
376 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
377 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
378 "%s: invalid UTF-16 string size value exceeds maximum.",
379 function );
380
381 return( -1 );
382 }
383 while( utf16_string_index < utf16_string_size )
384 {
385 /* Convert the UTF-16 string bytes into an Unicode character
386 */
387 if( libuna_unicode_character_copy_from_utf16(
388 &unicode_character,
389 utf16_string,
390 utf16_string_size,
391 &utf16_string_index,
392 error ) != 1 )
393 {
394 libcerror_error_set(
395 error,
396 LIBCERROR_ERROR_DOMAIN_CONVERSION,
397 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
398 "%s: unable to copy Unicode character from UTF-16 string.",
399 function );
400
401 return( -1 );
402 }
403 /* Convert the Unicode character into UTF-7 stream bytes
404 */
405 if( libuna_unicode_character_copy_to_utf7_stream(
406 unicode_character,
407 utf7_stream,
408 utf7_stream_size,
409 &utf7_stream_index,
410 &utf7_stream_base64_data,
411 error ) != 1 )
412 {
413 libcerror_error_set(
414 error,
415 LIBCERROR_ERROR_DOMAIN_CONVERSION,
416 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
417 "%s: unable to copy Unicode character to UTF-7 stream.",
418 function );
419
420 return( -1 );
421 }
422 if( unicode_character == 0 )
423 {
424 break;
425 }
426 }
427 return( 1 );
428 }
429
430 /* Determines the size of an UTF-7 stream from an UTF-32 string
431 * Returns 1 if successful or -1 on error
432 */
libuna_utf7_stream_size_from_utf32(const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,size_t * utf7_stream_size,libcerror_error_t ** error)433 int libuna_utf7_stream_size_from_utf32(
434 const libuna_utf32_character_t *utf32_string,
435 size_t utf32_string_size,
436 size_t *utf7_stream_size,
437 libcerror_error_t **error )
438 {
439 static char *function = "libuna_utf7_stream_size_from_utf32";
440 libuna_unicode_character_t unicode_character = 0;
441 size_t utf32_string_index = 0;
442 uint32_t utf7_stream_base64_data = 0;
443
444 if( utf32_string == NULL )
445 {
446 libcerror_error_set(
447 error,
448 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
449 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
450 "%s: invalid UTF-32 string.",
451 function );
452
453 return( -1 );
454 }
455 if( utf32_string_size > (size_t) SSIZE_MAX )
456 {
457 libcerror_error_set(
458 error,
459 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
460 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
461 "%s: invalid UTF-32 string size value exceeds maximum.",
462 function );
463
464 return( -1 );
465 }
466 if( utf7_stream_size == NULL )
467 {
468 libcerror_error_set(
469 error,
470 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
471 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
472 "%s: invalid UTF-7 stream size.",
473 function );
474
475 return( -1 );
476 }
477 while( utf32_string_index < utf32_string_size )
478 {
479 /* Convert the UTF-32 character bytes into an Unicode character
480 */
481 if( libuna_unicode_character_copy_from_utf32(
482 &unicode_character,
483 utf32_string,
484 utf32_string_size,
485 &utf32_string_index,
486 error ) != 1 )
487 {
488 libcerror_error_set(
489 error,
490 LIBCERROR_ERROR_DOMAIN_CONVERSION,
491 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
492 "%s: unable to copy Unicode character from UTF-32.",
493 function );
494
495 return( -1 );
496 }
497 /* Determine how many UTF-7 character bytes are required
498 */
499 if( libuna_unicode_character_size_to_utf7_stream(
500 unicode_character,
501 utf7_stream_size,
502 &utf7_stream_base64_data,
503 error ) != 1 )
504 {
505 libcerror_error_set(
506 error,
507 LIBCERROR_ERROR_DOMAIN_CONVERSION,
508 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
509 "%s: unable to determine size of Unicode character in UTF-7.",
510 function );
511
512 return( -1 );
513 }
514 if( unicode_character == 0 )
515 {
516 break;
517 }
518 }
519 return( 1 );
520 }
521
522 /* Copies an UTF-7 stream from an UTF-32 string
523 * Returns 1 if successful or -1 on error
524 */
libuna_utf7_stream_copy_from_utf32(uint8_t * utf7_stream,size_t utf7_stream_size,const libuna_utf32_character_t * utf32_string,size_t utf32_string_size,libcerror_error_t ** error)525 int libuna_utf7_stream_copy_from_utf32(
526 uint8_t *utf7_stream,
527 size_t utf7_stream_size,
528 const libuna_utf32_character_t *utf32_string,
529 size_t utf32_string_size,
530 libcerror_error_t **error )
531 {
532 static char *function = "libuna_utf7_stream_copy_from_utf32";
533 libuna_unicode_character_t unicode_character = 0;
534 size_t utf32_string_index = 0;
535 size_t utf7_stream_index = 0;
536 uint32_t utf7_stream_base64_data = 0;
537
538 if( utf7_stream == NULL )
539 {
540 libcerror_error_set(
541 error,
542 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
543 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
544 "%s: invalid UTF-7 stream.",
545 function );
546
547 return( -1 );
548 }
549 if( utf7_stream_size > (size_t) SSIZE_MAX )
550 {
551 libcerror_error_set(
552 error,
553 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
554 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
555 "%s: invalid UTF-7 stream size value exceeds maximum.",
556 function );
557
558 return( -1 );
559 }
560 if( utf32_string == NULL )
561 {
562 libcerror_error_set(
563 error,
564 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
565 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
566 "%s: invalid UTF-32 string.",
567 function );
568
569 return( -1 );
570 }
571 if( utf32_string_size > (size_t) SSIZE_MAX )
572 {
573 libcerror_error_set(
574 error,
575 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
576 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
577 "%s: invalid UTF-32 string size value exceeds maximum.",
578 function );
579
580 return( -1 );
581 }
582 while( utf32_string_index < utf32_string_size )
583 {
584 /* Convert the UTF-32 character bytes into an Unicode character
585 */
586 if( libuna_unicode_character_copy_from_utf32(
587 &unicode_character,
588 utf32_string,
589 utf32_string_size,
590 &utf32_string_index,
591 error ) != 1 )
592 {
593 libcerror_error_set(
594 error,
595 LIBCERROR_ERROR_DOMAIN_CONVERSION,
596 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
597 "%s: unable to copy Unicode character from UTF-32.",
598 function );
599
600 return( -1 );
601 }
602 /* Convert the Unicode character into UTF-7 character bytes
603 */
604 if( libuna_unicode_character_copy_to_utf7_stream(
605 unicode_character,
606 utf7_stream,
607 utf7_stream_size,
608 &utf7_stream_index,
609 &utf7_stream_base64_data,
610 error ) != 1 )
611 {
612 libcerror_error_set(
613 error,
614 LIBCERROR_ERROR_DOMAIN_CONVERSION,
615 LIBCERROR_CONVERSION_ERROR_OUTPUT_FAILED,
616 "%s: unable to copy Unicode character to UTF-7 stream.",
617 function );
618
619 return( -1 );
620 }
621 if( unicode_character == 0 )
622 {
623 break;
624 }
625 }
626 return( 1 );
627 }
628
629