Coverage Report

Created: 2024-02-25 07:20

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