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