1 /*
2 * Percent or URL encoded 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 <types.h>
24
25 #include "libuna_definitions.h"
26 #include "libuna_libcerror.h"
27 #include "libuna_types.h"
28 #include "libuna_url_stream.h"
29
30 /* Determines the size of a url stream from a byte stream
31 * Returns 1 if successful or -1 on error
32 */
libuna_url_stream_size_from_byte_stream(uint8_t * byte_stream,size_t byte_stream_size,size_t * url_stream_size,libcerror_error_t ** error)33 int libuna_url_stream_size_from_byte_stream(
34 uint8_t *byte_stream,
35 size_t byte_stream_size,
36 size_t *url_stream_size,
37 libcerror_error_t **error )
38 {
39 static char *function = "libuna_url_stream_size_from_byte_stream";
40 size_t byte_stream_index = 0;
41
42 if( byte_stream == NULL )
43 {
44 libcerror_error_set(
45 error,
46 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
47 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
48 "%s: invalid byte stream.",
49 function );
50
51 return( -1 );
52 }
53 if( byte_stream_size > (size_t) SSIZE_MAX )
54 {
55 libcerror_error_set(
56 error,
57 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
59 "%s: invalid byte stream size value exceeds maximum.",
60 function );
61
62 return( -1 );
63 }
64 if( url_stream_size == NULL )
65 {
66 libcerror_error_set(
67 error,
68 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
69 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
70 "%s: invalid url stream size.",
71 function );
72
73 return( -1 );
74 }
75 /* TODO what about end of string character */
76
77 *url_stream_size = 0;
78
79 /* Check if the byte stream contains
80 * reserved or non-allowed characters that need to be decoded
81 */
82 while( byte_stream_index < byte_stream_size )
83 {
84 /* A-Z is not a continous range on an EBCDIC based system
85 * it consists of the ranges: A-I, J-R, S-Z
86 */
87 if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'A' )
88 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'I' ) )
89 {
90 *url_stream_size += 1;
91 }
92 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'J' )
93 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'R' ) )
94 {
95 *url_stream_size += 1;
96 }
97 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'S' )
98 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'Z' ) )
99 {
100 *url_stream_size += 1;
101 }
102 /* a-z is not a continous range on an EBCDIC based system
103 * it consists of the ranges: a-i, j-r, s-z
104 */
105 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'a' )
106 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'i' ) )
107 {
108 *url_stream_size += 1;
109 }
110 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'j' )
111 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'r' ) )
112 {
113 *url_stream_size += 1;
114 }
115 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 's' )
116 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'z' ) )
117 {
118 *url_stream_size += 1;
119 }
120 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) '0' )
121 && ( byte_stream[ byte_stream_index ] <= (uint8_t) '9' ) )
122 {
123 *url_stream_size += 1;
124 }
125 else if( ( byte_stream[ byte_stream_index ] == (uint8_t) '-' )
126 || ( byte_stream[ byte_stream_index ] == (uint8_t) '_' )
127 || ( byte_stream[ byte_stream_index ] == (uint8_t) '.' )
128 || ( byte_stream[ byte_stream_index ] == (uint8_t) '`' ) )
129 {
130 *url_stream_size += 1;
131 }
132 else
133 {
134 *url_stream_size += 3;
135 }
136 byte_stream_index++;
137 }
138 return( 1 );
139 }
140
141 /* Copies a url stream from a byte stream
142 * Returns 1 if successful or -1 on error
143 */
libuna_url_stream_copy_from_byte_stream(uint8_t * url_stream,size_t url_stream_size,uint8_t * byte_stream,size_t byte_stream_size,libcerror_error_t ** error)144 int libuna_url_stream_copy_from_byte_stream(
145 uint8_t *url_stream,
146 size_t url_stream_size,
147 uint8_t *byte_stream,
148 size_t byte_stream_size,
149 libcerror_error_t **error )
150 {
151 static char *function = "libuna_url_stream_copy_from_byte_stream";
152 size_t url_stream_index = 0;
153 size_t byte_stream_index = 0;
154 uint8_t byte_value = 0;
155
156 if( url_stream == NULL )
157 {
158 libcerror_error_set(
159 error,
160 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
161 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
162 "%s: invalid url stream.",
163 function );
164
165 return( -1 );
166 }
167 if( url_stream_size > (size_t) SSIZE_MAX )
168 {
169 libcerror_error_set(
170 error,
171 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
173 "%s: invalid url stream size value exceeds maximum.",
174 function );
175
176 return( -1 );
177 }
178 if( byte_stream == NULL )
179 {
180 libcerror_error_set(
181 error,
182 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
183 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
184 "%s: invalid byte stream.",
185 function );
186
187 return( -1 );
188 }
189 if( byte_stream_size > (size_t) SSIZE_MAX )
190 {
191 libcerror_error_set(
192 error,
193 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
194 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
195 "%s: invalid byte stream size value exceeds maximum.",
196 function );
197
198 return( -1 );
199 }
200 /* TODO what about end of string character */
201
202 /* Check if the byte stream contains
203 * reserved or non-allowed characters that need to be decoded
204 */
205 while( byte_stream_index < byte_stream_size )
206 {
207 if( url_stream_index >= url_stream_size )
208 {
209 libcerror_error_set(
210 error,
211 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
212 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
213 "%s: url stream is too small.",
214 function );
215
216 return( -1 );
217 }
218 /* A-Z is not a continous range on an EBCDIC based system
219 * it consists of the ranges: A-I, J-R, S-Z
220 */
221 if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'A' )
222 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'I' ) )
223 {
224 url_stream[ url_stream_index++ ] = byte_stream[ byte_stream_index ];
225 }
226 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'J' )
227 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'R' ) )
228 {
229 url_stream[ url_stream_index++ ] = byte_stream[ byte_stream_index ];
230 }
231 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'S' )
232 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'Z' ) )
233 {
234 url_stream[ url_stream_index++ ] = byte_stream[ byte_stream_index ];
235 }
236 /* a-z is not a continous range on an EBCDIC based system
237 * it consists of the ranges: a-i, j-r, s-z
238 */
239 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'a' )
240 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'i' ) )
241 {
242 url_stream[ url_stream_index++ ] = byte_stream[ byte_stream_index ];
243 }
244 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 'j' )
245 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'r' ) )
246 {
247 url_stream[ url_stream_index++ ] = byte_stream[ byte_stream_index ];
248 }
249 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) 's' )
250 && ( byte_stream[ byte_stream_index ] <= (uint8_t) 'z' ) )
251 {
252 url_stream[ url_stream_index++ ] = byte_stream[ byte_stream_index ];
253 }
254 else if( ( byte_stream[ byte_stream_index ] >= (uint8_t) '0' )
255 && ( byte_stream[ byte_stream_index ] <= (uint8_t) '9' ) )
256 {
257 url_stream[ url_stream_index++ ] = byte_stream[ byte_stream_index ];
258 }
259 else if( ( byte_stream[ byte_stream_index ] == (uint8_t) '-' )
260 || ( byte_stream[ byte_stream_index ] == (uint8_t) '_' )
261 || ( byte_stream[ byte_stream_index ] == (uint8_t) '.' )
262 || ( byte_stream[ byte_stream_index ] == (uint8_t) '`' ) )
263 {
264 url_stream[ url_stream_index++ ] = byte_stream[ byte_stream_index ];
265 }
266 else
267 {
268 if( ( url_stream_index + 3 ) > url_stream_size )
269 {
270 libcerror_error_set(
271 error,
272 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
274 "%s: url stream is too small.",
275 function );
276
277 return( -1 );
278 }
279 url_stream[ url_stream_index++ ] = (uint8_t) '%';
280
281 byte_value = byte_stream[ byte_stream_index ] >> 4;
282
283 if( byte_value <= 9 )
284 {
285 url_stream[ url_stream_index++ ] = (uint8_t) '0' + byte_value;
286 }
287 else
288 {
289 url_stream[ url_stream_index++ ] = (uint8_t) 'A' + byte_value;
290 }
291 byte_value = byte_stream[ byte_stream_index ] & 0x0f;
292
293 if( byte_value < 9 )
294 {
295 url_stream[ url_stream_index++ ] = (uint8_t) '0' + byte_value;
296 }
297 else
298 {
299 url_stream[ url_stream_index++ ] = (uint8_t) 'A' + byte_value;
300 }
301 }
302 byte_stream_index++;
303 }
304 return( 1 );
305 }
306
307 /* Determines the size of a byte stream from a url stream
308 * Returns 1 if successful or -1 on error
309 */
libuna_url_stream_size_to_byte_stream(uint8_t * url_stream,size_t url_stream_size,size_t * byte_stream_size,libcerror_error_t ** error)310 int libuna_url_stream_size_to_byte_stream(
311 uint8_t *url_stream,
312 size_t url_stream_size,
313 size_t *byte_stream_size,
314 libcerror_error_t **error )
315 {
316 static char *function = "libuna_url_stream_size_to_byte_stream";
317 size_t url_stream_index = 0;
318
319 if( url_stream == NULL )
320 {
321 libcerror_error_set(
322 error,
323 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
324 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
325 "%s: invalid url stream.",
326 function );
327
328 return( -1 );
329 }
330 if( url_stream_size > (size_t) SSIZE_MAX )
331 {
332 libcerror_error_set(
333 error,
334 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
335 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
336 "%s: invalid url stream size value exceeds maximum.",
337 function );
338
339 return( -1 );
340 }
341 if( byte_stream_size == NULL )
342 {
343 libcerror_error_set(
344 error,
345 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
346 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
347 "%s: invalid byte stream size.",
348 function );
349
350 return( -1 );
351 }
352 *byte_stream_size = 0;
353
354 while( url_stream_index < url_stream_size )
355 {
356 if( url_stream[ url_stream_index ] == (uint8_t) '%' )
357 {
358 url_stream_index++;
359
360 if( ( url_stream_index + 2 ) > url_stream_size )
361 {
362 libcerror_error_set(
363 error,
364 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
365 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
366 "%s: url stream is too small.",
367 function );
368
369 return( -1 );
370 }
371 if( ( url_stream[ url_stream_index ] >= (uint8_t) 'A' )
372 && ( url_stream[ url_stream_index ] <= (uint8_t) 'F' ) )
373 {
374 }
375 else if( ( url_stream[ url_stream_index ] >= (uint8_t) 'a' )
376 && ( url_stream[ url_stream_index ] <= (uint8_t) 'f' ) )
377 {
378 }
379 else if( ( url_stream[ url_stream_index ] >= (uint8_t) '0' )
380 && ( url_stream[ url_stream_index ] <= (uint8_t) '9' ) )
381 {
382 }
383 else
384 {
385 libcerror_error_set(
386 error,
387 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
388 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
389 "%s: invalid URL encoded character.",
390 function );
391
392 return( -1 );
393 }
394 url_stream_index++;
395
396 if( ( url_stream[ url_stream_index ] >= (uint8_t) 'A' )
397 && ( url_stream[ url_stream_index ] <= (uint8_t) 'F' ) )
398 {
399 }
400 else if( ( url_stream[ url_stream_index ] >= (uint8_t) 'a' )
401 && ( url_stream[ url_stream_index ] <= (uint8_t) 'f' ) )
402 {
403 }
404 else if( ( url_stream[ url_stream_index ] >= (uint8_t) '0' )
405 && ( url_stream[ url_stream_index ] <= (uint8_t) '9' ) )
406 {
407 }
408 else
409 {
410 libcerror_error_set(
411 error,
412 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
413 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
414 "%s: invalid URL encoded character.",
415 function );
416
417 return( -1 );
418 }
419 url_stream_index++;
420 }
421 else
422 {
423 url_stream_index++;
424 }
425 *byte_stream_size += 1;
426 }
427 return( 1 );
428 }
429
430 /* Copies a byte stream from a url stream
431 * Returns 1 if successful or -1 on error
432 */
libuna_url_stream_copy_to_byte_stream(uint8_t * url_stream,size_t url_stream_size,uint8_t * byte_stream,size_t byte_stream_size,libcerror_error_t ** error)433 int libuna_url_stream_copy_to_byte_stream(
434 uint8_t *url_stream,
435 size_t url_stream_size,
436 uint8_t *byte_stream,
437 size_t byte_stream_size,
438 libcerror_error_t **error )
439 {
440 static char *function = "libuna_url_stream_copy_to_byte_stream";
441 size_t url_stream_index = 0;
442 size_t byte_stream_index = 0;
443 uint8_t byte_value = 0;
444
445 if( url_stream == NULL )
446 {
447 libcerror_error_set(
448 error,
449 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
450 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
451 "%s: invalid url stream.",
452 function );
453
454 return( -1 );
455 }
456 if( url_stream_size > (size_t) SSIZE_MAX )
457 {
458 libcerror_error_set(
459 error,
460 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
461 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
462 "%s: invalid url stream size value exceeds maximum.",
463 function );
464
465 return( -1 );
466 }
467 if( byte_stream == NULL )
468 {
469 libcerror_error_set(
470 error,
471 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
472 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
473 "%s: invalid byte stream.",
474 function );
475
476 return( -1 );
477 }
478 if( byte_stream_size > (size_t) SSIZE_MAX )
479 {
480 libcerror_error_set(
481 error,
482 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
483 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
484 "%s: invalid byte stream size value exceeds maximum.",
485 function );
486
487 return( -1 );
488 }
489 while( url_stream_index < url_stream_size )
490 {
491 if( byte_stream_index >= byte_stream_size )
492 {
493 libcerror_error_set(
494 error,
495 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
496 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
497 "%s: byte stream is too small.",
498 function );
499
500 return( -1 );
501 }
502 if( url_stream[ url_stream_index ] == (uint8_t) '%' )
503 {
504 url_stream_index++;
505
506 if( ( url_stream_index + 2 ) > url_stream_size )
507 {
508 libcerror_error_set(
509 error,
510 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
511 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
512 "%s: url stream is too small.",
513 function );
514
515 return( -1 );
516 }
517 if( ( url_stream[ url_stream_index ] >= (uint8_t) 'A' )
518 && ( url_stream[ url_stream_index ] <= (uint8_t) 'F' ) )
519 {
520 byte_value = url_stream[ url_stream_index ] - (uint8_t) 'A';
521 }
522 else if( ( url_stream[ url_stream_index ] >= (uint8_t) 'a' )
523 && ( url_stream[ url_stream_index ] <= (uint8_t) 'f' ) )
524 {
525 byte_value = url_stream[ url_stream_index ] - (uint8_t) 'a';
526 }
527 else if( ( url_stream[ url_stream_index ] >= (uint8_t) '0' )
528 && ( url_stream[ url_stream_index ] <= (uint8_t) '9' ) )
529 {
530 byte_value = url_stream[ url_stream_index ] - (uint8_t) '0';
531 }
532 else
533 {
534 libcerror_error_set(
535 error,
536 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
537 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
538 "%s: invalid URL encoded character.",
539 function );
540
541 return( -1 );
542 }
543 byte_value <<= 4;
544
545 url_stream_index++;
546
547 if( ( url_stream[ url_stream_index ] >= (uint8_t) 'A' )
548 && ( url_stream[ url_stream_index ] <= (uint8_t) 'F' ) )
549 {
550 byte_value += url_stream[ url_stream_index ] - (uint8_t) 'A';
551 }
552 else if( ( url_stream[ url_stream_index ] >= (uint8_t) 'a' )
553 && ( url_stream[ url_stream_index ] <= (uint8_t) 'f' ) )
554 {
555 byte_value += url_stream[ url_stream_index ] - (uint8_t) 'a';
556 }
557 else if( ( url_stream[ url_stream_index ] >= (uint8_t) '0' )
558 && ( url_stream[ url_stream_index ] <= (uint8_t) '9' ) )
559 {
560 byte_value += url_stream[ url_stream_index ] - (uint8_t) '0';
561 }
562 else
563 {
564 libcerror_error_set(
565 error,
566 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
567 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
568 "%s: invalid URL encoded character.",
569 function );
570
571 return( -1 );
572 }
573 url_stream_index++;
574
575 byte_stream[ byte_stream_index++ ] = byte_value;
576 }
577 else
578 {
579 byte_stream[ byte_stream_index++ ] = url_stream[ url_stream_index++ ];
580 }
581 }
582 return( 1 );
583 }
584
585