Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfplist/libfplist/libfplist_property.c
Line
Count
Source
1
/*
2
 * Property functions
3
 *
4
 * Copyright (C) 2016-2026, 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 <narrow_string.h>
25
#include <types.h>
26
27
#include "libfplist_definitions.h"
28
#include "libfplist_libcerror.h"
29
#include "libfplist_libcnotify.h"
30
#include "libfplist_libfguid.h"
31
#include "libfplist_libfvalue.h"
32
#include "libfplist_libuna.h"
33
#include "libfplist_property.h"
34
#include "libfplist_types.h"
35
#include "libfplist_xml_tag.h"
36
37
/* Creates a property
38
 * Make sure the value property is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libfplist_property_initialize(
42
     libfplist_property_t **property,
43
     libfplist_xml_tag_t *key_tag,
44
     libfplist_xml_tag_t *value_tag,
45
     libcerror_error_t **error )
46
29.1k
{
47
29.1k
  libfplist_internal_property_t *internal_property = NULL;
48
29.1k
  static char *function                            = "libfplist_property_initialize";
49
29.1k
  int result                                       = 0;
50
51
29.1k
  if( property == NULL )
52
0
  {
53
0
    libcerror_error_set(
54
0
     error,
55
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
56
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
57
0
     "%s: invalid property.",
58
0
     function );
59
60
0
    return( -1 );
61
0
  }
62
29.1k
  if( *property != NULL )
63
0
  {
64
0
    libcerror_error_set(
65
0
     error,
66
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
67
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
68
0
     "%s: invalid property value already set.",
69
0
     function );
70
71
0
    return( -1 );
72
0
  }
73
29.1k
  if( value_tag == NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
78
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
79
0
     "%s: invalid value XML tag.",
80
0
     function );
81
82
0
    return( -1 );
83
0
  }
84
29.1k
  if( key_tag != NULL )
85
4.64k
  {
86
4.64k
    result = libfplist_xml_tag_compare_name(
87
4.64k
              key_tag,
88
4.64k
              (uint8_t *) "key",
89
4.64k
              3,
90
4.64k
              error );
91
92
4.64k
    if( result == -1 )
93
0
    {
94
0
      libcerror_error_set(
95
0
       error,
96
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
97
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
98
0
       "%s: unable to compare name of key tag.",
99
0
       function );
100
101
0
      return( -1 );
102
0
    }
103
4.64k
    else if( result == 0 )
104
0
    {
105
0
      libcerror_error_set(
106
0
       error,
107
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
108
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
109
0
       "%s: unsupported key tag: %s.",
110
0
       function,
111
0
       key_tag->name );
112
113
0
      return( -1 );
114
0
    }
115
4.64k
  }
116
29.1k
  internal_property = memory_allocate_structure(
117
29.1k
                       libfplist_internal_property_t );
118
119
29.1k
  if( internal_property == NULL )
120
0
  {
121
0
    libcerror_error_set(
122
0
     error,
123
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
124
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
125
0
     "%s: unable to create property.",
126
0
     function );
127
128
0
    goto on_error;
129
0
  }
130
29.1k
  if( memory_set(
131
29.1k
       internal_property,
132
29.1k
       0,
133
29.1k
       sizeof( libfplist_internal_property_t ) ) == NULL )
134
0
  {
135
0
    libcerror_error_set(
136
0
     error,
137
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
138
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
139
0
     "%s: unable to clear property.",
140
0
     function );
141
142
0
    memory_free(
143
0
     internal_property );
144
145
0
    return( -1 );
146
0
  }
147
29.1k
  internal_property->key_tag   = key_tag;
148
29.1k
  internal_property->value_tag = value_tag;
149
150
29.1k
  *property = (libfplist_property_t *) internal_property;
151
152
29.1k
  return( 1 );
153
154
0
on_error:
155
0
  if( internal_property != NULL )
156
0
  {
157
0
    memory_free(
158
0
     internal_property );
159
0
  }
160
0
  return( -1 );
161
29.1k
}
162
163
/* Frees a property
164
 * Returns 1 if successful or -1 on error
165
 */
166
int libfplist_property_free(
167
    libfplist_property_t **property,
168
    libcerror_error_t **error )
169
29.1k
{
170
29.1k
  libfplist_internal_property_t *internal_property = NULL;
171
29.1k
  static char *function                            = "libfplist_property_free";
172
173
29.1k
  if( property == NULL )
174
0
  {
175
0
    libcerror_error_set(
176
0
     error,
177
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
178
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
179
0
     "%s: invalid property.",
180
0
     function );
181
182
0
    return( -1 );
183
0
  }
184
29.1k
  if( *property != NULL )
185
29.1k
  {
186
29.1k
    internal_property = (libfplist_internal_property_t *) *property;
187
29.1k
    *property         = NULL;
188
189
    /* The key_tag and value_tag are referenced and freed elsewhere */
190
191
29.1k
    memory_free(
192
29.1k
     internal_property );
193
29.1k
  }
194
29.1k
  return( 1 );
195
29.1k
}
196
197
/* Retrieves the value type
198
 * Returns 1 if successful or -1 on error
199
 */
200
int libfplist_property_get_value_type(
201
     libfplist_property_t *property,
202
     int *value_type,
203
     libcerror_error_t **error )
204
38
{
205
38
  libfplist_internal_property_t *internal_property = NULL;
206
38
  static char *function                            = "libfplist_property_get_value_type";
207
208
38
  if( property == NULL )
209
0
  {
210
0
    libcerror_error_set(
211
0
     error,
212
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
213
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
214
0
     "%s: invalid property.",
215
0
     function );
216
217
0
    return( -1 );
218
0
  }
219
38
  internal_property = (libfplist_internal_property_t *) property;
220
221
38
  if( internal_property->value_tag == NULL )
222
0
  {
223
0
    libcerror_error_set(
224
0
     error,
225
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
226
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
227
0
     "%s: invalid property - missing value XML tag.",
228
0
     function );
229
230
0
    return( -1 );
231
0
  }
232
38
  if( value_type == NULL )
233
0
  {
234
0
    libcerror_error_set(
235
0
     error,
236
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
237
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
238
0
     "%s: invalid value type.",
239
0
     function );
240
241
0
    return( -1 );
242
0
  }
243
38
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
244
38
  {
245
38
    if( libfplist_xml_tag_get_value_type(
246
38
         internal_property->value_tag,
247
38
         &( internal_property->value_type ),
248
38
         error ) != 1 )
249
0
    {
250
0
      libcerror_error_set(
251
0
       error,
252
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
253
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
254
0
       "%s: unable to retrieve value type.",
255
0
       function );
256
257
0
      return( -1 );
258
0
    }
259
38
  }
260
38
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
261
0
  {
262
0
    libcerror_error_set(
263
0
     error,
264
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
265
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
266
0
     "%s: unsupported value type.",
267
0
     function );
268
269
0
    return( -1 );
270
0
  }
271
38
  *value_type = internal_property->value_type;
272
273
38
  return( 1 );
274
38
}
275
276
/* Retrieves the value (binary) data size
277
 * Returns 1 if successful or -1 on error
278
 */
279
int libfplist_property_get_value_data_size(
280
     libfplist_property_t *property,
281
     size_t *data_size,
282
     libcerror_error_t **error )
283
{
284
  libfplist_internal_property_t *internal_property = NULL;
285
  uint8_t *value_data                              = NULL;
286
  static char *function                            = "libfplist_property_get_value_data_size";
287
  size_t value_length                              = 0;
288
289
  if( property == NULL )
290
  {
291
    libcerror_error_set(
292
     error,
293
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
294
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
295
     "%s: invalid property.",
296
     function );
297
298
    return( -1 );
299
  }
300
  internal_property = (libfplist_internal_property_t *) property;
301
302
  if( internal_property->value_tag == NULL )
303
  {
304
    libcerror_error_set(
305
     error,
306
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
307
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
308
     "%s: invalid property - missing value XML tag.",
309
     function );
310
311
    return( -1 );
312
  }
313
  if( data_size == NULL )
314
  {
315
    libcerror_error_set(
316
     error,
317
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
318
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
319
     "%s: invalid data size.",
320
     function );
321
322
    return( -1 );
323
  }
324
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
325
  {
326
    if( libfplist_xml_tag_get_value_type(
327
         internal_property->value_tag,
328
         &( internal_property->value_type ),
329
         error ) != 1 )
330
    {
331
      libcerror_error_set(
332
       error,
333
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
334
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
335
       "%s: unable to retrieve value type.",
336
       function );
337
338
      return( -1 );
339
    }
340
  }
341
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_BINARY_DATA )
342
  {
343
    libcerror_error_set(
344
     error,
345
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
346
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
347
     "%s: unsupported value type.",
348
     function );
349
350
    return( -1 );
351
  }
352
  if( ( internal_property->value_tag->value == NULL )
353
   || ( internal_property->value_tag->value_size == 0 ) )
354
  {
355
    *data_size = 0;
356
  }
357
  else
358
  {
359
    value_data   = internal_property->value_tag->value;
360
    value_length = internal_property->value_tag->value_size - 1;
361
362
    /* The base64 conversion function does not like an empty first line
363
     */
364
    if( ( value_data != NULL )
365
     && ( value_data[ 0 ] == '\n' ) )
366
    {
367
      value_data   += 1;
368
      value_length -= 1;
369
    }
370
#if defined( HAVE_DEBUG_OUTPUT )
371
    if( libcnotify_verbose != 0 )
372
    {
373
      libcnotify_printf(
374
       "%s: base64 encoded data:\n",
375
       function );
376
      libcnotify_print_data(
377
       value_data,
378
       value_length,
379
       0 );
380
    }
381
#endif
382
    if( libuna_base64_stream_size_to_byte_stream(
383
         value_data,
384
         value_length,
385
         data_size,
386
         LIBUNA_BASE64_VARIANT_ALPHABET_NORMAL | LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_NONE | LIBUNA_BASE64_VARIANT_PADDING_REQUIRED,
387
         LIBUNA_BASE64_FLAG_STRIP_WHITESPACE,
388
         error ) != 1 )
389
    {
390
      libcerror_error_set(
391
       error,
392
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
393
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
394
       "%s: unable to determine size of base64 encoded data.",
395
       function );
396
397
      return( -1 );
398
    }
399
  }
400
  return( 1 );
401
}
402
403
/* Copies the value (binary) data
404
 * Returns 1 if successful or -1 on error
405
 */
406
int libfplist_property_get_value_data(
407
     libfplist_property_t *property,
408
     uint8_t *data,
409
     size_t data_size,
410
     libcerror_error_t **error )
411
{
412
  libfplist_internal_property_t *internal_property = NULL;
413
  uint8_t *value_data                              = NULL;
414
  static char *function                            = "libfplist_property_get_value_data";
415
  size_t value_length                              = 0;
416
417
  if( property == NULL )
418
  {
419
    libcerror_error_set(
420
     error,
421
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
422
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
423
     "%s: invalid property.",
424
     function );
425
426
    return( -1 );
427
  }
428
  internal_property = (libfplist_internal_property_t *) property;
429
430
  if( internal_property->value_tag == NULL )
431
  {
432
    libcerror_error_set(
433
     error,
434
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
435
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
436
     "%s: invalid property - missing value XML tag.",
437
     function );
438
439
    return( -1 );
440
  }
441
  if( data == NULL )
442
  {
443
    libcerror_error_set(
444
     error,
445
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
446
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
447
     "%s: invalid data.",
448
     function );
449
450
    return( -1 );
451
  }
452
  if( data_size > (size_t) SSIZE_MAX )
453
  {
454
    libcerror_error_set(
455
     error,
456
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
457
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
458
     "%s: invalid data size value exceeds maximum.",
459
     function );
460
461
    return( -1 );
462
  }
463
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
464
  {
465
    if( libfplist_xml_tag_get_value_type(
466
         internal_property->value_tag,
467
         &( internal_property->value_type ),
468
         error ) != 1 )
469
    {
470
      libcerror_error_set(
471
       error,
472
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
473
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
474
       "%s: unable to retrieve value type.",
475
       function );
476
477
      return( -1 );
478
    }
479
  }
480
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_BINARY_DATA )
481
  {
482
    libcerror_error_set(
483
     error,
484
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
485
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
486
     "%s: unsupported value type.",
487
     function );
488
489
    return( -1 );
490
  }
491
  if( ( internal_property->value_tag->value != NULL )
492
   && ( internal_property->value_tag->value_size != 0 ) )
493
  {
494
    value_data   = internal_property->value_tag->value;
495
    value_length = internal_property->value_tag->value_size - 1;
496
497
    /* The base64 conversion function does not like an empty first line
498
     */
499
    if( ( value_data != NULL )
500
     && ( value_data[ 0 ] == '\n' ) )
501
    {
502
      value_data   += 1;
503
      value_length -= 1;
504
    }
505
#if defined( HAVE_DEBUG_OUTPUT )
506
    if( libcnotify_verbose != 0 )
507
    {
508
      libcnotify_printf(
509
       "%s: base64 encoded data:\n",
510
       function );
511
      libcnotify_print_data(
512
       value_data,
513
       value_length,
514
       0 );
515
    }
516
#endif
517
    if( libuna_base64_stream_copy_to_byte_stream(
518
         value_data,
519
         value_length,
520
         data,
521
         data_size,
522
         LIBUNA_BASE64_VARIANT_ALPHABET_NORMAL | LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_NONE | LIBUNA_BASE64_VARIANT_PADDING_REQUIRED,
523
         LIBUNA_BASE64_FLAG_STRIP_WHITESPACE,
524
         error ) != 1 )
525
    {
526
      libcerror_error_set(
527
       error,
528
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
529
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
530
       "%s: unable to copy base64 encoded data to byte stream.",
531
       function );
532
533
      return( -1 );
534
    }
535
  }
536
  return( 1 );
537
}
538
539
/* Retrieves an integer value
540
 * Returns 1 if successful or -1 on error
541
 */
542
int libfplist_property_get_value_integer(
543
     libfplist_property_t *property,
544
     uint64_t *value_64bit,
545
     libcerror_error_t **error )
546
52
{
547
52
  libfplist_internal_property_t *internal_property = NULL;
548
52
  static char *function                            = "libfplist_property_get_value_integer";
549
52
  uint32_t string_format_flags                     = 0;
550
551
52
  if( property == NULL )
552
0
  {
553
0
    libcerror_error_set(
554
0
     error,
555
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
556
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
557
0
     "%s: invalid property.",
558
0
     function );
559
560
0
    return( -1 );
561
0
  }
562
52
  internal_property = (libfplist_internal_property_t *) property;
563
564
52
  if( internal_property->value_tag == NULL )
565
0
  {
566
0
    libcerror_error_set(
567
0
     error,
568
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
569
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
570
0
     "%s: invalid property - missing value XML tag.",
571
0
     function );
572
573
0
    return( -1 );
574
0
  }
575
52
  if( internal_property->value_tag->value == NULL )
576
14
  {
577
14
    libcerror_error_set(
578
14
     error,
579
14
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
580
14
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
581
14
     "%s: invalid property - invalid value XML tag - missing value.",
582
14
     function );
583
584
14
    return( -1 );
585
14
  }
586
38
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
587
38
  {
588
38
    if( libfplist_xml_tag_get_value_type(
589
38
         internal_property->value_tag,
590
38
         &( internal_property->value_type ),
591
38
         error ) != 1 )
592
0
    {
593
0
      libcerror_error_set(
594
0
       error,
595
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
596
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
597
0
       "%s: unable to retrieve value type.",
598
0
       function );
599
600
0
      return( -1 );
601
0
    }
602
38
  }
603
38
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_INTEGER )
604
38
  {
605
38
    libcerror_error_set(
606
38
     error,
607
38
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
608
38
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
609
38
     "%s: unsupported value type.",
610
38
     function );
611
612
38
    return( -1 );
613
38
  }
614
0
  if( ( internal_property->value_tag->value_size > 4 )
615
0
   && ( internal_property->value_tag->value[ 0 ] == '0' )
616
0
   && ( ( internal_property->value_tag->value[ 1 ] == 'x' )
617
0
    ||  ( internal_property->value_tag->value[ 1 ] == 'X' ) ) )
618
0
  {
619
0
    string_format_flags = LIBFVALUE_INTEGER_FORMAT_TYPE_HEXADECIMAL;
620
0
  }
621
0
  else
622
0
  {
623
0
    string_format_flags = LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL | LIBFVALUE_INTEGER_FORMAT_FLAG_UNSIGNED;
624
0
  }
625
/* TODO add support for size attribute e.g. size="64" */
626
0
  if( libfvalue_utf8_string_copy_to_integer(
627
0
       internal_property->value_tag->value,
628
0
       internal_property->value_tag->value_size - 1,
629
0
       (uint64_t *) value_64bit,
630
0
       64,
631
0
       string_format_flags,
632
0
       error ) != 1 )
633
0
  {
634
0
    libcerror_error_set(
635
0
     error,
636
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
637
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
638
0
     "%s: unable to convert value to integer.",
639
0
     function );
640
641
0
    return( -1 );
642
0
  }
643
0
  return( 1 );
644
0
}
645
646
/* Retrieves a string value
647
 * Returns 1 if successful or -1 on error
648
 */
649
int libfplist_property_get_value_string(
650
     libfplist_property_t *property,
651
     uint8_t **string,
652
     size_t *string_size,
653
     libcerror_error_t **error )
654
20.3k
{
655
20.3k
  libfplist_internal_property_t *internal_property = NULL;
656
20.3k
  static char *function                            = "libfplist_property_get_value_string";
657
658
20.3k
  if( property == NULL )
659
0
  {
660
0
    libcerror_error_set(
661
0
     error,
662
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
663
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
664
0
     "%s: invalid property.",
665
0
     function );
666
667
0
    return( -1 );
668
0
  }
669
20.3k
  internal_property = (libfplist_internal_property_t *) property;
670
671
20.3k
  if( internal_property->value_tag == NULL )
672
0
  {
673
0
    libcerror_error_set(
674
0
     error,
675
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
676
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
677
0
     "%s: invalid property - missing value XML tag.",
678
0
     function );
679
680
0
    return( -1 );
681
0
  }
682
20.3k
  if( internal_property->value_tag->value == NULL )
683
2
  {
684
2
    libcerror_error_set(
685
2
     error,
686
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
687
2
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
688
2
     "%s: invalid property - invalid value XML tag - missing value.",
689
2
     function );
690
691
2
    return( -1 );
692
2
  }
693
20.3k
  if( string == NULL )
694
0
  {
695
0
    libcerror_error_set(
696
0
     error,
697
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
698
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
699
0
     "%s: invalid string.",
700
0
     function );
701
702
0
    return( -1 );
703
0
  }
704
20.3k
  if( *string != NULL )
705
0
  {
706
0
    libcerror_error_set(
707
0
     error,
708
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
709
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
710
0
     "%s: invalid string value already set.",
711
0
     function );
712
713
0
    return( -1 );
714
0
  }
715
20.3k
  if( string_size == NULL )
716
0
  {
717
0
    libcerror_error_set(
718
0
     error,
719
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
720
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
721
0
     "%s: invalid string size.",
722
0
     function );
723
724
0
    return( -1 );
725
0
  }
726
20.3k
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
727
20.3k
  {
728
20.3k
    if( libfplist_xml_tag_get_value_type(
729
20.3k
         internal_property->value_tag,
730
20.3k
         &( internal_property->value_type ),
731
20.3k
         error ) != 1 )
732
0
    {
733
0
      libcerror_error_set(
734
0
       error,
735
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
736
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
737
0
       "%s: unable to retrieve value type.",
738
0
       function );
739
740
0
      return( -1 );
741
0
    }
742
20.3k
  }
743
20.3k
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_STRING )
744
4
  {
745
4
    libcerror_error_set(
746
4
     error,
747
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
748
4
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
749
4
     "%s: unsupported value type.",
750
4
     function );
751
752
4
    return( -1 );
753
4
  }
754
20.3k
  if( ( internal_property->value_tag->value_size == 0 )
755
20.3k
   || ( internal_property->value_tag->value_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
756
0
  {
757
0
    libcerror_error_set(
758
0
     error,
759
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
760
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
761
0
     "%s: invalid property - invalid value tag - value size value out of bounds.",
762
0
     function );
763
764
0
    return( -1 );
765
0
  }
766
20.3k
  *string = memory_allocate(
767
20.3k
             sizeof( uint8_t ) * internal_property->value_tag->value_size );
768
769
20.3k
  if( *string == NULL )
770
0
  {
771
0
    libcerror_error_set(
772
0
     error,
773
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
774
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
775
0
     "%s: unable to create string.",
776
0
     function );
777
778
0
    goto on_error;
779
0
  }
780
20.3k
  *string_size = internal_property->value_tag->value_size;
781
782
20.3k
  if( memory_copy(
783
20.3k
       *string,
784
20.3k
       internal_property->value_tag->value,
785
20.3k
       internal_property->value_tag->value_size ) == NULL )
786
0
  {
787
0
    libcerror_error_set(
788
0
     error,
789
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
790
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
791
0
     "%s: unable to copy string.",
792
0
     function );
793
794
0
    goto on_error;
795
0
  }
796
20.3k
  return( 1 );
797
798
0
on_error:
799
0
  if( *string != NULL )
800
0
  {
801
0
    memory_free(
802
0
     *string );
803
804
0
    *string = NULL;
805
0
  }
806
0
  *string_size = 0;
807
808
0
  return( -1 );
809
20.3k
}
810
811
/* Copies an UUID string value to a byte stream
812
 * Returns 1 if successful or -1 on error
813
 */
814
int libfplist_property_value_uuid_string_copy_to_byte_stream(
815
     libfplist_property_t *property,
816
     uint8_t *byte_stream,
817
     size_t byte_stream_size,
818
     libcerror_error_t **error )
819
20.0k
{
820
20.0k
  libfguid_identifier_t *guid = NULL;
821
20.0k
  uint8_t *string             = NULL;
822
20.0k
  static char *function       = "libfplist_property_value_uuid_string_copy_to_byte_stream";
823
20.0k
  size_t string_size          = 0;
824
825
20.0k
  if( libfplist_property_get_value_string(
826
20.0k
       property,
827
20.0k
       &string,
828
20.0k
       &string_size,
829
20.0k
       error ) != 1 )
830
3
  {
831
3
    libcerror_error_set(
832
3
     error,
833
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
834
3
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
835
3
     "%s: unable to retrieve logical volume family identifier.",
836
3
     function );
837
838
3
    goto on_error;
839
3
  }
840
20.0k
  if( string_size == 0 )
841
0
  {
842
0
    libcerror_error_set(
843
0
     error,
844
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
845
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
846
0
     "%s: invalid string size value out of bounds.",
847
0
     function );
848
849
0
    goto on_error;
850
0
  }
851
20.0k
  if( libfguid_identifier_initialize(
852
20.0k
       &guid,
853
20.0k
       error ) != 1 )
854
0
  {
855
0
    libcerror_error_set(
856
0
     error,
857
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
858
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
859
0
     "%s: unable to create GUID.",
860
0
     function );
861
862
0
    goto on_error;
863
0
  }
864
20.0k
  if( libfguid_identifier_copy_from_utf8_string(
865
20.0k
       guid,
866
20.0k
       string,
867
20.0k
       string_size - 1,
868
20.0k
       LIBFGUID_STRING_FORMAT_FLAG_USE_MIXED_CASE,
869
20.0k
       error ) != 1 )
870
199
  {
871
199
    libcerror_error_set(
872
199
     error,
873
199
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
874
199
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
875
199
     "%s: unable to copy GUID from string.",
876
199
     function );
877
878
199
    goto on_error;
879
199
  }
880
19.8k
  memory_free(
881
19.8k
   string );
882
883
19.8k
  string = NULL;
884
885
19.8k
  if( libfguid_identifier_copy_to_byte_stream(
886
19.8k
       guid,
887
19.8k
       byte_stream,
888
19.8k
       byte_stream_size,
889
19.8k
       LIBFGUID_ENDIAN_BIG,
890
19.8k
       error ) != 1 )
891
0
  {
892
0
    libcerror_error_set(
893
0
     error,
894
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
895
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
896
0
     "%s: unable to copy GUID to byte stream.",
897
0
     function );
898
899
0
    goto on_error;
900
0
  }
901
19.8k
  if( libfguid_identifier_free(
902
19.8k
       &guid,
903
19.8k
       error ) != 1 )
904
0
  {
905
0
    libcerror_error_set(
906
0
     error,
907
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
908
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
909
0
     "%s: unable to free GUID.",
910
0
     function );
911
912
0
    goto on_error;
913
0
  }
914
19.8k
  return( 1 );
915
916
202
on_error:
917
202
  if( string != NULL )
918
199
  {
919
199
    memory_free(
920
199
     string );
921
199
  }
922
202
  if( guid != NULL )
923
199
  {
924
199
    libfguid_identifier_free(
925
199
     &guid,
926
199
     NULL );
927
199
  }
928
202
  return( -1 );
929
19.8k
}
930
931
/* Retrieves the number of array entries
932
 * Returns 1 if successful or -1 on error
933
 */
934
int libfplist_property_get_array_number_of_entries(
935
     libfplist_property_t *property,
936
     int *number_of_entries,
937
     libcerror_error_t **error )
938
1.45k
{
939
1.45k
  libfplist_internal_property_t *internal_property = NULL;
940
1.45k
  libfplist_xml_tag_t *element_tag                 = NULL;
941
1.45k
  static char *function                            = "libfplist_property_get_array_number_of_entries";
942
1.45k
  int element_index                                = 0;
943
1.45k
  int number_of_elements                           = 0;
944
1.45k
  int number_of_nodes                              = 0;
945
1.45k
  int result                                       = 0;
946
947
1.45k
  if( property == NULL )
948
0
  {
949
0
    libcerror_error_set(
950
0
     error,
951
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
952
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
953
0
     "%s: invalid property.",
954
0
     function );
955
956
0
    return( -1 );
957
0
  }
958
1.45k
  internal_property = (libfplist_internal_property_t *) property;
959
960
1.45k
  if( internal_property->value_tag == NULL )
961
0
  {
962
0
    libcerror_error_set(
963
0
     error,
964
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
965
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
966
0
     "%s: invalid property - missing value XML tag.",
967
0
     function );
968
969
0
    return( -1 );
970
0
  }
971
1.45k
  if( number_of_entries == NULL )
972
0
  {
973
0
    libcerror_error_set(
974
0
     error,
975
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
976
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
977
0
     "%s: invalid number of entries.",
978
0
     function );
979
980
0
    return( -1 );
981
0
  }
982
1.45k
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
983
1.45k
  {
984
1.45k
    if( libfplist_xml_tag_get_value_type(
985
1.45k
         internal_property->value_tag,
986
1.45k
         &( internal_property->value_type ),
987
1.45k
         error ) != 1 )
988
0
    {
989
0
      libcerror_error_set(
990
0
       error,
991
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
992
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
993
0
       "%s: unable to retrieve value type.",
994
0
       function );
995
996
0
      return( -1 );
997
0
    }
998
1.45k
  }
999
1.45k
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_ARRAY )
1000
27
  {
1001
27
    libcerror_error_set(
1002
27
     error,
1003
27
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1004
27
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1005
27
     "%s: unsupported value type.",
1006
27
     function );
1007
1008
27
    return( -1 );
1009
27
  }
1010
1.42k
  if( libfplist_xml_tag_get_number_of_elements(
1011
1.42k
       internal_property->value_tag,
1012
1.42k
       &number_of_elements,
1013
1.42k
       error ) != 1 )
1014
0
  {
1015
0
    libcerror_error_set(
1016
0
     error,
1017
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1018
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1019
0
     "%s: unable to retrieve number of elements.",
1020
0
     function );
1021
1022
0
    return( -1 );
1023
0
  }
1024
1.42k
  for( element_index = 0;
1025
81.5k
       element_index < number_of_elements;
1026
80.1k
       element_index++ )
1027
80.1k
  {
1028
80.1k
    if( libfplist_xml_tag_get_element(
1029
80.1k
         internal_property->value_tag,
1030
80.1k
         element_index,
1031
80.1k
         &element_tag,
1032
80.1k
         error ) != 1 )
1033
0
    {
1034
0
      libcerror_error_set(
1035
0
       error,
1036
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1037
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1038
0
       "%s: unable to retrieve element: %d.",
1039
0
       function,
1040
0
       element_index );
1041
1042
0
      return( -1 );
1043
0
    }
1044
    /* Ignore text nodes
1045
     */
1046
80.1k
    result = libfplist_xml_tag_compare_name(
1047
80.1k
              element_tag,
1048
80.1k
              (uint8_t *) "text",
1049
80.1k
              4,
1050
80.1k
              error );
1051
1052
80.1k
    if( result == -1 )
1053
0
    {
1054
0
      libcerror_error_set(
1055
0
       error,
1056
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1057
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1058
0
       "%s: unable to compare name of value tag.",
1059
0
       function );
1060
1061
0
      return( -1 );
1062
0
    }
1063
80.1k
    else if( result == 0 )
1064
65.5k
    {
1065
65.5k
      number_of_nodes++;
1066
65.5k
    }
1067
80.1k
  }
1068
1.42k
  *number_of_entries = number_of_nodes;
1069
1070
1.42k
  return( 1 );
1071
1.42k
}
1072
1073
/* Retrieves a specific array entry
1074
 * Returns 1 if successful or -1 on error
1075
 */
1076
int libfplist_property_get_array_entry_by_index(
1077
     libfplist_property_t *property,
1078
     int array_entry_index,
1079
     libfplist_property_t **array_entry,
1080
     libcerror_error_t **error )
1081
22.7k
{
1082
22.7k
  libfplist_internal_property_t *internal_property = NULL;
1083
22.7k
  libfplist_xml_tag_t *value_tag                   = NULL;
1084
22.7k
  static char *function                            = "libfplist_property_get_array_entry_by_index";
1085
22.7k
  int entry_index                                  = 0;
1086
22.7k
  int element_index                                = 0;
1087
22.7k
  int number_of_elements                           = 0;
1088
22.7k
  int result                                       = 0;
1089
1090
22.7k
  if( property == NULL )
1091
0
  {
1092
0
    libcerror_error_set(
1093
0
     error,
1094
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1095
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1096
0
     "%s: invalid property.",
1097
0
     function );
1098
1099
0
    return( -1 );
1100
0
  }
1101
22.7k
  internal_property = (libfplist_internal_property_t *) property;
1102
1103
22.7k
  if( internal_property->value_tag == NULL )
1104
0
  {
1105
0
    libcerror_error_set(
1106
0
     error,
1107
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1108
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1109
0
     "%s: invalid property - missing value XML tag.",
1110
0
     function );
1111
1112
0
    return( -1 );
1113
0
  }
1114
22.7k
  if( array_entry_index < 0 )
1115
0
  {
1116
0
    libcerror_error_set(
1117
0
     error,
1118
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1119
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1120
0
     "%s: invalid array entry index value out of bounds.",
1121
0
     function );
1122
1123
0
    return( -1 );
1124
0
  }
1125
22.7k
  if( array_entry == NULL )
1126
0
  {
1127
0
    libcerror_error_set(
1128
0
     error,
1129
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1130
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1131
0
     "%s: invalid array entry.",
1132
0
     function );
1133
1134
0
    return( -1 );
1135
0
  }
1136
22.7k
  if( *array_entry != NULL )
1137
0
  {
1138
0
    libcerror_error_set(
1139
0
     error,
1140
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1141
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1142
0
     "%s: invalid array entry value already set.",
1143
0
     function );
1144
1145
0
    return( -1 );
1146
0
  }
1147
22.7k
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
1148
0
  {
1149
0
    if( libfplist_xml_tag_get_value_type(
1150
0
         internal_property->value_tag,
1151
0
         &( internal_property->value_type ),
1152
0
         error ) != 1 )
1153
0
    {
1154
0
      libcerror_error_set(
1155
0
       error,
1156
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1157
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1158
0
       "%s: unable to retrieve value type.",
1159
0
       function );
1160
1161
0
      return( -1 );
1162
0
    }
1163
0
  }
1164
22.7k
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_ARRAY )
1165
0
  {
1166
0
    libcerror_error_set(
1167
0
     error,
1168
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1169
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1170
0
     "%s: unsupported value type.",
1171
0
     function );
1172
1173
0
    return( -1 );
1174
0
  }
1175
22.7k
  if( libfplist_xml_tag_get_number_of_elements(
1176
22.7k
       internal_property->value_tag,
1177
22.7k
       &number_of_elements,
1178
22.7k
       error ) != 1 )
1179
0
  {
1180
0
    libcerror_error_set(
1181
0
     error,
1182
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1183
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1184
0
     "%s: unable to retrieve number of elements.",
1185
0
     function );
1186
1187
0
    return( -1 );
1188
0
  }
1189
22.7k
  entry_index = array_entry_index;
1190
1191
22.7k
  element_index = 0;
1192
1193
2.14M
  while( element_index < number_of_elements )
1194
2.14M
  {
1195
2.14M
    if( libfplist_xml_tag_get_element(
1196
2.14M
         internal_property->value_tag,
1197
2.14M
         element_index,
1198
2.14M
         &value_tag,
1199
2.14M
         error ) != 1 )
1200
0
    {
1201
0
      libcerror_error_set(
1202
0
       error,
1203
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1204
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1205
0
       "%s: unable to retrieve element: %d.",
1206
0
       function,
1207
0
       element_index );
1208
1209
0
      return( -1 );
1210
0
    }
1211
    /* Ignore text nodes
1212
     */
1213
2.14M
    result = libfplist_xml_tag_compare_name(
1214
2.14M
              value_tag,
1215
2.14M
              (uint8_t *) "text",
1216
2.14M
              4,
1217
2.14M
              error );
1218
1219
2.14M
    if( result == -1 )
1220
0
    {
1221
0
      libcerror_error_set(
1222
0
       error,
1223
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1224
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1225
0
       "%s: unable to compare name of value tag.",
1226
0
       function );
1227
1228
0
      return( -1 );
1229
0
    }
1230
2.14M
    else if( result == 0 )
1231
2.13M
    {
1232
2.13M
      if( entry_index == 0 )
1233
22.7k
      {
1234
22.7k
        break;
1235
22.7k
      }
1236
2.11M
      entry_index--;
1237
2.11M
    }
1238
2.12M
    element_index++;
1239
2.12M
  }
1240
22.7k
  if( element_index >= number_of_elements )
1241
0
  {
1242
0
    return( 0 );
1243
0
  }
1244
22.7k
  if( libfplist_property_initialize(
1245
22.7k
       array_entry,
1246
22.7k
       NULL,
1247
22.7k
       value_tag,
1248
22.7k
       error ) != 1 )
1249
0
  {
1250
0
    libcerror_error_set(
1251
0
     error,
1252
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1253
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1254
0
     "%s: unable to create array entry: %d.",
1255
0
     function,
1256
0
     array_entry_index );
1257
1258
0
    return( -1 );
1259
0
  }
1260
22.7k
  return( 1 );
1261
22.7k
}
1262
1263
/* Retrieves the sub property for the specific UTF-8 encoded name
1264
 * Returns 1 if successful, 0 if no such sub property or -1 on error
1265
 */
1266
int libfplist_property_get_sub_property_by_utf8_name(
1267
     libfplist_property_t *property,
1268
     const uint8_t *utf8_string,
1269
     size_t utf8_string_length,
1270
     libfplist_property_t **sub_property,
1271
     libcerror_error_t **error )
1272
6.79k
{
1273
6.79k
  libfplist_internal_property_t *internal_property = NULL;
1274
6.79k
  libfplist_xml_tag_t *key_tag                     = NULL;
1275
6.79k
  libfplist_xml_tag_t *value_tag                   = NULL;
1276
6.79k
  static char *function                            = "libfplist_property_get_sub_property_by_utf8_name";
1277
6.79k
  int element_index                                = 0;
1278
6.79k
  int number_of_elements                           = 0;
1279
6.79k
  int result                                       = 0;
1280
1281
6.79k
  if( property == NULL )
1282
0
  {
1283
0
    libcerror_error_set(
1284
0
     error,
1285
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1286
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1287
0
     "%s: invalid property.",
1288
0
     function );
1289
1290
0
    return( -1 );
1291
0
  }
1292
6.79k
  internal_property = (libfplist_internal_property_t *) property;
1293
1294
6.79k
  if( internal_property->value_tag == NULL )
1295
0
  {
1296
0
    libcerror_error_set(
1297
0
     error,
1298
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1299
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1300
0
     "%s: invalid property - missing value XML tag.",
1301
0
     function );
1302
1303
0
    return( -1 );
1304
0
  }
1305
6.79k
  if( utf8_string == NULL )
1306
0
  {
1307
0
    libcerror_error_set(
1308
0
     error,
1309
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1310
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1311
0
     "%s: invalid UTF-8 string.",
1312
0
     function );
1313
1314
0
    return( -1 );
1315
0
  }
1316
6.79k
  if( utf8_string_length > (size_t) ( SSIZE_MAX - 1 ) )
1317
0
  {
1318
0
    libcerror_error_set(
1319
0
     error,
1320
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1321
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1322
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
1323
0
     function );
1324
1325
0
    return( -1 );
1326
0
  }
1327
6.79k
  if( sub_property == NULL )
1328
0
  {
1329
0
    libcerror_error_set(
1330
0
     error,
1331
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1332
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1333
0
     "%s: invalid sub property.",
1334
0
     function );
1335
1336
0
    return( -1 );
1337
0
  }
1338
6.79k
  if( *sub_property != NULL )
1339
0
  {
1340
0
    libcerror_error_set(
1341
0
     error,
1342
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1343
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1344
0
     "%s: invalid sub property value already set.",
1345
0
     function );
1346
1347
0
    return( -1 );
1348
0
  }
1349
6.79k
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
1350
5.57k
  {
1351
5.57k
    if( libfplist_xml_tag_get_value_type(
1352
5.57k
         internal_property->value_tag,
1353
5.57k
         &( internal_property->value_type ),
1354
5.57k
         error ) != 1 )
1355
0
    {
1356
0
      libcerror_error_set(
1357
0
       error,
1358
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1359
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1360
0
       "%s: unable to retrieve value type.",
1361
0
       function );
1362
1363
0
      return( -1 );
1364
0
    }
1365
5.57k
  }
1366
6.79k
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_DICTIONARY )
1367
44
  {
1368
44
    libcerror_error_set(
1369
44
     error,
1370
44
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1371
44
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1372
44
     "%s: unsupported value type.",
1373
44
     function );
1374
1375
44
    return( -1 );
1376
44
  }
1377
6.74k
  if( libfplist_xml_tag_get_number_of_elements(
1378
6.74k
       internal_property->value_tag,
1379
6.74k
       &number_of_elements,
1380
6.74k
       error ) != 1 )
1381
0
  {
1382
0
    libcerror_error_set(
1383
0
     error,
1384
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1385
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1386
0
     "%s: unable to retrieve number of elements.",
1387
0
     function );
1388
1389
0
    return( -1 );
1390
0
  }
1391
6.74k
  element_index = 0;
1392
1393
351k
  while( element_index < number_of_elements )
1394
349k
  {
1395
349k
    if( libfplist_xml_tag_get_element(
1396
349k
         internal_property->value_tag,
1397
349k
         element_index,
1398
349k
         &key_tag,
1399
349k
         error ) != 1 )
1400
0
    {
1401
0
      libcerror_error_set(
1402
0
       error,
1403
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1404
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1405
0
       "%s: unable to retrieve element: %d.",
1406
0
       function,
1407
0
       element_index );
1408
1409
0
      return( -1 );
1410
0
    }
1411
349k
    result = libfplist_xml_tag_compare_name(
1412
349k
              key_tag,
1413
349k
              (uint8_t *) "key",
1414
349k
              3,
1415
349k
              error );
1416
1417
349k
    if( result == -1 )
1418
0
    {
1419
0
      libcerror_error_set(
1420
0
       error,
1421
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1422
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1423
0
       "%s: unable to compare name of key tag.",
1424
0
       function );
1425
1426
0
      return( -1 );
1427
0
    }
1428
349k
    else if( result != 0 )
1429
17.3k
    {
1430
17.3k
      if( ( key_tag->value_size == ( utf8_string_length + 1 ) )
1431
7.83k
       && narrow_string_compare(
1432
7.83k
           key_tag->value,
1433
7.83k
           utf8_string,
1434
7.83k
           utf8_string_length ) == 0 )
1435
4.79k
      {
1436
4.79k
        break;
1437
4.79k
      }
1438
17.3k
    }
1439
344k
    element_index++;
1440
344k
  }
1441
6.74k
  if( element_index >= number_of_elements )
1442
1.95k
  {
1443
1.95k
    return( 0 );
1444
1.95k
  }
1445
4.79k
  element_index++;
1446
1447
5.10k
  while( element_index < number_of_elements )
1448
4.95k
  {
1449
4.95k
    if( libfplist_xml_tag_get_element(
1450
4.95k
         internal_property->value_tag,
1451
4.95k
         element_index,
1452
4.95k
         &value_tag,
1453
4.95k
         error ) != 1 )
1454
0
    {
1455
0
      libcerror_error_set(
1456
0
       error,
1457
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1458
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1459
0
       "%s: unable to retrieve element: %d.",
1460
0
       function,
1461
0
       element_index );
1462
1463
0
      return( -1 );
1464
0
    }
1465
    /* Ignore text nodes
1466
     */
1467
4.95k
    result = libfplist_xml_tag_compare_name(
1468
4.95k
              value_tag,
1469
4.95k
              (uint8_t *) "text",
1470
4.95k
              4,
1471
4.95k
              error );
1472
1473
4.95k
    if( result == -1 )
1474
0
    {
1475
0
      libcerror_error_set(
1476
0
       error,
1477
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1478
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1479
0
       "%s: unable to compare name of value tag.",
1480
0
       function );
1481
1482
0
      return( -1 );
1483
0
    }
1484
4.95k
    else if( result == 0 )
1485
4.64k
    {
1486
4.64k
      break;
1487
4.64k
    }
1488
311
    element_index++;
1489
311
  }
1490
4.79k
  if( element_index >= number_of_elements )
1491
149
  {
1492
149
    return( 0 );
1493
149
  }
1494
4.64k
  if( libfplist_property_initialize(
1495
4.64k
       sub_property,
1496
4.64k
       key_tag,
1497
4.64k
       value_tag,
1498
4.64k
       error ) != 1 )
1499
0
  {
1500
0
    libcerror_error_set(
1501
0
     error,
1502
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1503
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1504
0
     "%s: unable to create sub property.",
1505
0
     function );
1506
1507
0
    return( -1 );
1508
0
  }
1509
4.64k
  return( 1 );
1510
4.64k
}
1511