Coverage Report

Created: 2025-06-24 07:14

/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
23.7k
{
47
23.7k
  libfplist_internal_property_t *internal_property = NULL;
48
23.7k
  static char *function                            = "libfplist_property_initialize";
49
23.7k
  int result                                       = 0;
50
51
23.7k
  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
23.7k
  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
23.7k
  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
23.7k
  if( key_tag != NULL )
85
5.14k
  {
86
5.14k
    result = libfplist_xml_tag_compare_name(
87
5.14k
              key_tag,
88
5.14k
              (uint8_t *) "key",
89
5.14k
              3,
90
5.14k
              error );
91
92
5.14k
    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
5.14k
    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
5.14k
  }
116
23.7k
  internal_property = memory_allocate_structure(
117
23.7k
                       libfplist_internal_property_t );
118
119
23.7k
  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
23.7k
  if( memory_set(
131
23.7k
       internal_property,
132
23.7k
       0,
133
23.7k
       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
23.7k
  internal_property->key_tag   = key_tag;
148
23.7k
  internal_property->value_tag = value_tag;
149
150
23.7k
  *property = (libfplist_property_t *) internal_property;
151
152
23.7k
  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
23.7k
}
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
23.7k
{
170
23.7k
  libfplist_internal_property_t *internal_property = NULL;
171
23.7k
  static char *function                            = "libfplist_property_free";
172
173
23.7k
  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
23.7k
  if( *property != NULL )
185
23.7k
  {
186
23.7k
    internal_property = (libfplist_internal_property_t *) *property;
187
23.7k
    *property         = NULL;
188
189
    /* The key_tag and value_tag are referenced and freed elsewhere */
190
191
23.7k
    memory_free(
192
23.7k
     internal_property );
193
23.7k
  }
194
23.7k
  return( 1 );
195
23.7k
}
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
40
{
205
40
  libfplist_internal_property_t *internal_property = NULL;
206
40
  static char *function                            = "libfplist_property_get_value_type";
207
208
40
  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
40
  internal_property = (libfplist_internal_property_t *) property;
220
221
40
  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
40
  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
40
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
244
40
  {
245
40
    if( libfplist_xml_tag_get_value_type(
246
40
         internal_property->value_tag,
247
40
         &( internal_property->value_type ),
248
40
         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
40
  }
260
40
  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
40
  *value_type = internal_property->value_type;
272
273
40
  return( 1 );
274
40
}
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
2.16k
{
284
2.16k
  libfplist_internal_property_t *internal_property = NULL;
285
2.16k
  uint8_t *value_data                              = NULL;
286
2.16k
  static char *function                            = "libfplist_property_get_value_data_size";
287
2.16k
  size_t value_length                              = 0;
288
289
2.16k
  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
2.16k
  internal_property = (libfplist_internal_property_t *) property;
301
302
2.16k
  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
2.16k
  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
2.16k
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
325
2.16k
  {
326
2.16k
    if( libfplist_xml_tag_get_value_type(
327
2.16k
         internal_property->value_tag,
328
2.16k
         &( internal_property->value_type ),
329
2.16k
         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
2.16k
  }
341
2.16k
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_BINARY_DATA )
342
2
  {
343
2
    libcerror_error_set(
344
2
     error,
345
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
346
2
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
347
2
     "%s: unsupported value type.",
348
2
     function );
349
350
2
    return( -1 );
351
2
  }
352
2.16k
  value_data   = internal_property->value_tag->value;
353
2.16k
  value_length = internal_property->value_tag->value_size - 1;
354
355
  /* The base64 conversion function does not like an empty first line
356
   */
357
2.16k
  if( ( value_data != NULL )
358
2.16k
   && ( value_data[ 0 ] == '\n' ) )
359
473
  {
360
473
    value_data   += 1;
361
473
    value_length -= 1;
362
473
  }
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
2.16k
  if( libuna_base64_stream_size_to_byte_stream(
376
2.16k
       value_data,
377
2.16k
       value_length,
378
2.16k
       data_size,
379
2.16k
       LIBUNA_BASE64_VARIANT_ALPHABET_NORMAL | LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_NONE | LIBUNA_BASE64_VARIANT_PADDING_REQUIRED,
380
2.16k
       LIBUNA_BASE64_FLAG_STRIP_WHITESPACE,
381
2.16k
       error ) != 1 )
382
119
  {
383
119
    libcerror_error_set(
384
119
     error,
385
119
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
386
119
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
387
119
     "%s: unable to determine size of base64 encoded data.",
388
119
     function );
389
390
119
    return( -1 );
391
119
  }
392
2.04k
  return( 1 );
393
2.16k
}
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
2.04k
{
404
2.04k
  libfplist_internal_property_t *internal_property = NULL;
405
2.04k
  uint8_t *value_data                              = NULL;
406
2.04k
  static char *function                            = "libfplist_property_get_value_data";
407
2.04k
  size_t value_length                              = 0;
408
409
2.04k
  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
2.04k
  internal_property = (libfplist_internal_property_t *) property;
421
422
2.04k
  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
2.04k
  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
2.04k
  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
2.04k
  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
2.04k
  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
2.04k
  value_data   = internal_property->value_tag->value;
484
2.04k
  value_length = internal_property->value_tag->value_size - 1;
485
486
  /* The base64 conversion function does not like an empty first line
487
   */
488
2.04k
  if( ( value_data != NULL )
489
2.04k
   && ( value_data[ 0 ] == '\n' ) )
490
466
  {
491
466
    value_data   += 1;
492
466
    value_length -= 1;
493
466
  }
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
2.04k
  if( libuna_base64_stream_copy_to_byte_stream(
507
2.04k
       value_data,
508
2.04k
       value_length,
509
2.04k
       data,
510
2.04k
       data_size,
511
2.04k
       LIBUNA_BASE64_VARIANT_ALPHABET_NORMAL | LIBUNA_BASE64_VARIANT_CHARACTER_LIMIT_NONE | LIBUNA_BASE64_VARIANT_PADDING_REQUIRED,
512
2.04k
       LIBUNA_BASE64_FLAG_STRIP_WHITESPACE,
513
2.04k
       error ) != 1 )
514
156
  {
515
156
    libcerror_error_set(
516
156
     error,
517
156
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
518
156
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
519
156
     "%s: unable to copy base64 encoded data to byte stream.",
520
156
     function );
521
522
156
    return( -1 );
523
156
  }
524
1.88k
  return( 1 );
525
2.04k
}
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
50
{
535
50
  libfplist_internal_property_t *internal_property = NULL;
536
50
  static char *function                            = "libfplist_property_get_value_integer";
537
50
  uint32_t string_format_flags                     = 0;
538
539
50
  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
50
  internal_property = (libfplist_internal_property_t *) property;
551
552
50
  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
50
  if( internal_property->value_tag->value == NULL )
564
15
  {
565
15
    libcerror_error_set(
566
15
     error,
567
15
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
568
15
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
569
15
     "%s: invalid property - invalid value XML tag - missing value.",
570
15
     function );
571
572
15
    return( -1 );
573
15
  }
574
35
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
575
35
  {
576
35
    if( libfplist_xml_tag_get_value_type(
577
35
         internal_property->value_tag,
578
35
         &( internal_property->value_type ),
579
35
         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
35
  }
591
35
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_INTEGER )
592
35
  {
593
35
    libcerror_error_set(
594
35
     error,
595
35
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
596
35
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
597
35
     "%s: unsupported value type.",
598
35
     function );
599
600
35
    return( -1 );
601
35
  }
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
13.3k
{
643
13.3k
  libfplist_internal_property_t *internal_property = NULL;
644
13.3k
  static char *function                            = "libfplist_property_get_value_string";
645
646
13.3k
  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
13.3k
  internal_property = (libfplist_internal_property_t *) property;
658
659
13.3k
  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
13.3k
  if( internal_property->value_tag->value == NULL )
671
3
  {
672
3
    libcerror_error_set(
673
3
     error,
674
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
675
3
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
676
3
     "%s: invalid property - invalid value XML tag - missing value.",
677
3
     function );
678
679
3
    return( -1 );
680
3
  }
681
13.3k
  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
13.3k
  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
13.3k
  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
13.3k
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
715
13.3k
  {
716
13.3k
    if( libfplist_xml_tag_get_value_type(
717
13.3k
         internal_property->value_tag,
718
13.3k
         &( internal_property->value_type ),
719
13.3k
         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
13.3k
  }
731
13.3k
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_STRING )
732
4
  {
733
4
    libcerror_error_set(
734
4
     error,
735
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
736
4
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
737
4
     "%s: unsupported value type.",
738
4
     function );
739
740
4
    return( -1 );
741
4
  }
742
13.3k
  if( ( internal_property->value_tag->value_size == 0 )
743
13.3k
   || ( 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
13.3k
  *string = memory_allocate(
755
13.3k
             sizeof( uint8_t ) * internal_property->value_tag->value_size );
756
757
13.3k
  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
13.3k
  *string_size = internal_property->value_tag->value_size;
769
770
13.3k
  if( memory_copy(
771
13.3k
       *string,
772
13.3k
       internal_property->value_tag->value,
773
13.3k
       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
13.3k
  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
13.3k
}
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
13.1k
{
808
13.1k
  libfguid_identifier_t *guid = NULL;
809
13.1k
  uint8_t *string             = NULL;
810
13.1k
  static char *function       = "libfplist_property_value_uuid_string_copy_to_byte_stream";
811
13.1k
  size_t string_size          = 0;
812
813
13.1k
  if( libfplist_property_get_value_string(
814
13.1k
       property,
815
13.1k
       &string,
816
13.1k
       &string_size,
817
13.1k
       error ) != 1 )
818
4
  {
819
4
    libcerror_error_set(
820
4
     error,
821
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
822
4
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
823
4
     "%s: unable to retrieve logical volume family identifier.",
824
4
     function );
825
826
4
    goto on_error;
827
4
  }
828
13.1k
  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
13.1k
  if( libfguid_identifier_initialize(
840
13.1k
       &guid,
841
13.1k
       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
13.1k
  if( libfguid_identifier_copy_from_utf8_string(
853
13.1k
       guid,
854
13.1k
       string,
855
13.1k
       string_size - 1,
856
13.1k
       LIBFGUID_STRING_FORMAT_FLAG_USE_MIXED_CASE,
857
13.1k
       error ) != 1 )
858
192
  {
859
192
    libcerror_error_set(
860
192
     error,
861
192
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
862
192
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
863
192
     "%s: unable to copy GUID from string.",
864
192
     function );
865
866
192
    goto on_error;
867
192
  }
868
12.9k
  memory_free(
869
12.9k
   string );
870
871
12.9k
  string = NULL;
872
873
12.9k
  if( libfguid_identifier_copy_to_byte_stream(
874
12.9k
       guid,
875
12.9k
       byte_stream,
876
12.9k
       byte_stream_size,
877
12.9k
       LIBFGUID_ENDIAN_BIG,
878
12.9k
       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
12.9k
  if( libfguid_identifier_free(
890
12.9k
       &guid,
891
12.9k
       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
12.9k
  return( 1 );
903
904
196
on_error:
905
196
  if( string != NULL )
906
192
  {
907
192
    memory_free(
908
192
     string );
909
192
  }
910
196
  if( guid != NULL )
911
192
  {
912
192
    libfguid_identifier_free(
913
192
     &guid,
914
192
     NULL );
915
192
  }
916
196
  return( -1 );
917
12.9k
}
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.33k
{
927
1.33k
  libfplist_internal_property_t *internal_property = NULL;
928
1.33k
  libfplist_xml_tag_t *element_tag                 = NULL;
929
1.33k
  static char *function                            = "libfplist_property_get_array_number_of_entries";
930
1.33k
  int element_index                                = 0;
931
1.33k
  int number_of_elements                           = 0;
932
1.33k
  int number_of_nodes                              = 0;
933
1.33k
  int result                                       = 0;
934
935
1.33k
  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.33k
  internal_property = (libfplist_internal_property_t *) property;
947
948
1.33k
  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.33k
  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.33k
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
971
1.33k
  {
972
1.33k
    if( libfplist_xml_tag_get_value_type(
973
1.33k
         internal_property->value_tag,
974
1.33k
         &( internal_property->value_type ),
975
1.33k
         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.33k
  }
987
1.33k
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_ARRAY )
988
32
  {
989
32
    libcerror_error_set(
990
32
     error,
991
32
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
992
32
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
993
32
     "%s: unsupported value type.",
994
32
     function );
995
996
32
    return( -1 );
997
32
  }
998
1.30k
  if( libfplist_xml_tag_get_number_of_elements(
999
1.30k
       internal_property->value_tag,
1000
1.30k
       &number_of_elements,
1001
1.30k
       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.30k
  for( element_index = 0;
1013
68.6k
       element_index < number_of_elements;
1014
67.3k
       element_index++ )
1015
67.3k
  {
1016
67.3k
    if( libfplist_xml_tag_get_element(
1017
67.3k
         internal_property->value_tag,
1018
67.3k
         element_index,
1019
67.3k
         &element_tag,
1020
67.3k
         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
67.3k
    result = libfplist_xml_tag_compare_name(
1035
67.3k
              element_tag,
1036
67.3k
              (uint8_t *) "text",
1037
67.3k
              4,
1038
67.3k
              error );
1039
1040
67.3k
    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
67.3k
    else if( result == 0 )
1052
53.1k
    {
1053
53.1k
      number_of_nodes++;
1054
53.1k
    }
1055
67.3k
  }
1056
1.30k
  *number_of_entries = number_of_nodes;
1057
1058
1.30k
  return( 1 );
1059
1.30k
}
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
16.9k
{
1070
16.9k
  libfplist_internal_property_t *internal_property = NULL;
1071
16.9k
  libfplist_xml_tag_t *value_tag                   = NULL;
1072
16.9k
  static char *function                            = "libfplist_property_get_array_entry_by_index";
1073
16.9k
  int entry_index                                  = 0;
1074
16.9k
  int element_index                                = 0;
1075
16.9k
  int number_of_elements                           = 0;
1076
16.9k
  int result                                       = 0;
1077
1078
16.9k
  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
16.9k
  internal_property = (libfplist_internal_property_t *) property;
1090
1091
16.9k
  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
16.9k
  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
16.9k
  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
16.9k
  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
16.9k
  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
16.9k
  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
16.9k
  if( libfplist_xml_tag_get_number_of_elements(
1164
16.9k
       internal_property->value_tag,
1165
16.9k
       &number_of_elements,
1166
16.9k
       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
16.9k
  entry_index = array_entry_index;
1178
1179
16.9k
  element_index = 0;
1180
1181
1.17M
  while( element_index < number_of_elements )
1182
1.17M
  {
1183
1.17M
    if( libfplist_xml_tag_get_element(
1184
1.17M
         internal_property->value_tag,
1185
1.17M
         element_index,
1186
1.17M
         &value_tag,
1187
1.17M
         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.17M
    result = libfplist_xml_tag_compare_name(
1202
1.17M
              value_tag,
1203
1.17M
              (uint8_t *) "text",
1204
1.17M
              4,
1205
1.17M
              error );
1206
1207
1.17M
    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.17M
    else if( result == 0 )
1219
1.16M
    {
1220
1.16M
      if( entry_index == 0 )
1221
16.9k
      {
1222
16.9k
        break;
1223
16.9k
      }
1224
1.15M
      entry_index--;
1225
1.15M
    }
1226
1.16M
    element_index++;
1227
1.16M
  }
1228
16.9k
  if( element_index >= number_of_elements )
1229
0
  {
1230
0
    return( 0 );
1231
0
  }
1232
16.9k
  if( libfplist_property_initialize(
1233
16.9k
       array_entry,
1234
16.9k
       NULL,
1235
16.9k
       value_tag,
1236
16.9k
       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
16.9k
  return( 1 );
1249
16.9k
}
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.67k
{
1261
7.67k
  libfplist_internal_property_t *internal_property = NULL;
1262
7.67k
  libfplist_xml_tag_t *key_tag                     = NULL;
1263
7.67k
  libfplist_xml_tag_t *value_tag                   = NULL;
1264
7.67k
  static char *function                            = "libfplist_property_get_sub_property_by_utf8_name";
1265
7.67k
  int element_index                                = 0;
1266
7.67k
  int number_of_elements                           = 0;
1267
7.67k
  int result                                       = 0;
1268
1269
7.67k
  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.67k
  internal_property = (libfplist_internal_property_t *) property;
1281
1282
7.67k
  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.67k
  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.67k
  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.67k
  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.67k
  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.67k
  if( internal_property->value_type == LIBFPLIST_VALUE_TYPE_UNKNOWN )
1338
6.52k
  {
1339
6.52k
    if( libfplist_xml_tag_get_value_type(
1340
6.52k
         internal_property->value_tag,
1341
6.52k
         &( internal_property->value_type ),
1342
6.52k
         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
6.52k
  }
1354
7.67k
  if( internal_property->value_type != LIBFPLIST_VALUE_TYPE_DICTIONARY )
1355
35
  {
1356
35
    libcerror_error_set(
1357
35
     error,
1358
35
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1359
35
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1360
35
     "%s: unsupported value type.",
1361
35
     function );
1362
1363
35
    return( -1 );
1364
35
  }
1365
7.63k
  if( libfplist_xml_tag_get_number_of_elements(
1366
7.63k
       internal_property->value_tag,
1367
7.63k
       &number_of_elements,
1368
7.63k
       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.63k
  element_index = 0;
1380
1381
338k
  while( element_index < number_of_elements )
1382
336k
  {
1383
336k
    if( libfplist_xml_tag_get_element(
1384
336k
         internal_property->value_tag,
1385
336k
         element_index,
1386
336k
         &key_tag,
1387
336k
         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
336k
    result = libfplist_xml_tag_compare_name(
1400
336k
              key_tag,
1401
336k
              (uint8_t *) "key",
1402
336k
              3,
1403
336k
              error );
1404
1405
336k
    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
336k
    else if( result != 0 )
1417
26.3k
    {
1418
26.3k
      if( ( key_tag->value_size == ( utf8_string_length + 1 ) )
1419
26.3k
       && narrow_string_compare(
1420
9.55k
           key_tag->value,
1421
9.55k
           utf8_string,
1422
9.55k
           utf8_string_length ) == 0 )
1423
5.24k
      {
1424
5.24k
        break;
1425
5.24k
      }
1426
26.3k
    }
1427
331k
    element_index++;
1428
331k
  }
1429
7.63k
  if( element_index >= number_of_elements )
1430
2.39k
  {
1431
2.39k
    return( 0 );
1432
2.39k
  }
1433
5.24k
  element_index++;
1434
1435
5.48k
  while( element_index < number_of_elements )
1436
5.38k
  {
1437
5.38k
    if( libfplist_xml_tag_get_element(
1438
5.38k
         internal_property->value_tag,
1439
5.38k
         element_index,
1440
5.38k
         &value_tag,
1441
5.38k
         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
5.38k
    result = libfplist_xml_tag_compare_name(
1456
5.38k
              value_tag,
1457
5.38k
              (uint8_t *) "text",
1458
5.38k
              4,
1459
5.38k
              error );
1460
1461
5.38k
    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
5.38k
    else if( result == 0 )
1473
5.14k
    {
1474
5.14k
      break;
1475
5.14k
    }
1476
239
    element_index++;
1477
239
  }
1478
5.24k
  if( element_index >= number_of_elements )
1479
98
  {
1480
98
    return( 0 );
1481
98
  }
1482
5.14k
  if( libfplist_property_initialize(
1483
5.14k
       sub_property,
1484
5.14k
       key_tag,
1485
5.14k
       value_tag,
1486
5.14k
       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
5.14k
  return( 1 );
1498
5.14k
}
1499