Coverage Report

Created: 2025-06-22 07:35

/src/libmsiecf/libmsiecf/libmsiecf_url_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * URL values functions
3
 *
4
 * Copyright (C) 2009-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 <byte_stream.h>
24
#include <memory.h>
25
#include <system_string.h>
26
#include <types.h>
27
28
#include "libmsiecf_debug.h"
29
#include "libmsiecf_definitions.h"
30
#include "libmsiecf_hash.h"
31
#include "libmsiecf_io_handle.h"
32
#include "libmsiecf_libbfio.h"
33
#include "libmsiecf_libcerror.h"
34
#include "libmsiecf_libcnotify.h"
35
#include "libmsiecf_libfdatetime.h"
36
#include "libmsiecf_libfole.h"
37
#include "libmsiecf_libfvalue.h"
38
#include "libmsiecf_property_type.h"
39
#include "libmsiecf_url_values.h"
40
41
#include "msiecf_url_record.h"
42
43
/* Creates URL values
44
 * Make sure the value url_values is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libmsiecf_url_values_initialize(
48
     libmsiecf_url_values_t **url_values,
49
     libcerror_error_t **error )
50
600
{
51
600
  static char *function = "libmsiecf_url_values_initialize";
52
53
600
  if( url_values == NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59
0
     "%s: invalid url values.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
600
  if( *url_values != NULL )
65
0
  {
66
0
    libcerror_error_set(
67
0
     error,
68
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
69
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
70
0
     "%s: invalid url values value already set.",
71
0
     function );
72
73
0
    return( -1 );
74
0
  }
75
600
  *url_values = memory_allocate_structure(
76
600
                 libmsiecf_url_values_t );
77
78
600
  if( *url_values == NULL )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
83
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
84
0
     "%s: unable to create URL values.",
85
0
     function );
86
87
0
    goto on_error;
88
0
  }
89
600
  if( memory_set(
90
600
       *url_values,
91
600
       0,
92
600
       sizeof( libmsiecf_url_values_t ) ) == NULL )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
97
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
98
0
     "%s: unable to clear URL values.",
99
0
     function );
100
101
0
    goto on_error;
102
0
  }
103
600
  return( 1 );
104
105
0
on_error:
106
0
  if( *url_values != NULL )
107
0
  {
108
0
    memory_free(
109
0
     *url_values );
110
111
0
    *url_values = NULL;
112
0
  }
113
0
  return( -1 );
114
600
}
115
116
/* Frees URL values
117
 * Returns 1 if successful or -1 on error
118
 */
119
int libmsiecf_url_values_free(
120
     libmsiecf_url_values_t **url_values,
121
     libcerror_error_t **error )
122
600
{
123
600
  static char *function = "libmsiecf_url_values_free";
124
600
  int result            = 1;
125
126
600
  if( url_values == NULL )
127
0
  {
128
0
    libcerror_error_set(
129
0
     error,
130
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
131
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
132
0
     "%s: invalid URL values.",
133
0
     function );
134
135
0
    return( -1 );
136
0
  }
137
600
  if( *url_values != NULL )
138
600
  {
139
600
    if( ( *url_values )->location != NULL )
140
432
    {
141
432
      if( libfvalue_value_free(
142
432
           &( ( *url_values )->location ),
143
432
           error ) != 1 )
144
0
      {
145
0
        libcerror_error_set(
146
0
         error,
147
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
148
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
149
0
         "%s: unable to free location value.",
150
0
         function );
151
152
0
        result = -1;
153
0
      }
154
432
    }
155
600
    if( ( *url_values )->filename != NULL )
156
163
    {
157
163
      if( libfvalue_value_free(
158
163
           &( ( *url_values )->filename ),
159
163
           error ) != 1 )
160
0
      {
161
0
        libcerror_error_set(
162
0
         error,
163
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
164
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
165
0
         "%s: unable to free filename value.",
166
0
         function );
167
168
0
        result = -1;
169
0
      }
170
163
    }
171
600
    if( ( *url_values )->data != NULL )
172
33
    {
173
33
      memory_free(
174
33
       ( *url_values )->data );
175
33
    }
176
600
    memory_free(
177
600
     *url_values );
178
179
600
    *url_values = NULL;
180
600
  }
181
600
  return( result );
182
600
}
183
184
/* Reads the URL values from an URL record
185
 * Returns 1 if successful or -1 on error
186
 */
187
int libmsiecf_url_values_read_data(
188
     libmsiecf_url_values_t *url_values,
189
     libmsiecf_io_handle_t *io_handle,
190
     const uint8_t *data,
191
     size_t data_size,
192
     uint8_t item_flags,
193
     libcerror_error_t **error )
194
573
{
195
573
  static char *function             = "libmsiecf_url_values_read_data";
196
573
  size_t required_data_size         = 0;
197
573
  ssize_t value_size                = 0;
198
573
  uint32_t cache_entry_flags        = 0;
199
573
  uint32_t filename_offset          = 0;
200
573
  uint32_t location_offset          = 0;
201
573
  uint32_t unknown_offset           = 0;
202
573
  uint32_t url_data_offset          = 0;
203
573
  uint32_t url_data_size            = 0;
204
573
  uint16_t first_year               = 0;
205
573
  uint16_t second_year              = 0;
206
573
  uint8_t first_day_of_month        = 0;
207
573
  uint8_t first_month               = 0;
208
573
  uint8_t number_of_days            = 0;
209
573
  uint8_t second_day_of_month       = 0;
210
573
  uint8_t second_month              = 0;
211
212
#if defined( HAVE_DEBUG_OUTPUT )
213
  const uint8_t *visited_entry_data = NULL;
214
  size_t string_index               = 0;
215
  uint32_t value_32bit              = 0;
216
  uint16_t value_16bit              = 0;
217
  int visited_entry_index           = 0;
218
#endif
219
220
573
  if( url_values == NULL )
221
0
  {
222
0
    libcerror_error_set(
223
0
     error,
224
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
225
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
226
0
     "%s: invalid URL values.",
227
0
     function );
228
229
0
    return( -1 );
230
0
  }
231
573
  if( io_handle == NULL )
232
0
  {
233
0
    libcerror_error_set(
234
0
     error,
235
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
236
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
237
0
     "%s: invalid IO handle.",
238
0
     function );
239
240
0
    return( -1 );
241
0
  }
242
573
  if( ( io_handle->major_version == 4 )
243
573
   && ( io_handle->minor_version == 7 ) )
244
3
  {
245
3
    required_data_size = sizeof( msiecf_url_record_header_v47_t );
246
3
  }
247
570
  else if( ( io_handle->major_version == 5 )
248
570
        && ( io_handle->minor_version == 2 ) )
249
570
  {
250
570
    required_data_size = sizeof( msiecf_url_record_header_v52_t );
251
570
  }
252
0
  else
253
0
  {
254
0
    libcerror_error_set(
255
0
     error,
256
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
257
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
258
0
     "%s: unsupported format version: %d.%d.",
259
0
     function,
260
0
     io_handle->major_version,
261
0
     io_handle->minor_version );
262
263
0
    goto on_error;
264
0
  }
265
573
  if( data == NULL )
266
0
  {
267
0
    libcerror_error_set(
268
0
     error,
269
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
270
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
271
0
     "%s: invalid data.",
272
0
     function );
273
274
0
    return( -1 );
275
0
  }
276
573
  if( data_size < required_data_size )
277
0
  {
278
0
    libcerror_error_set(
279
0
     error,
280
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
281
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
282
0
     "%s: invalid data size value too small.",
283
0
     function );
284
285
0
    return( -1 );
286
0
  }
287
573
  if( data_size > (size_t) SSIZE_MAX )
288
0
  {
289
0
    libcerror_error_set(
290
0
     error,
291
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
292
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
293
0
     "%s: invalid data size value exceeds maximum.",
294
0
     function );
295
296
0
    return( -1 );
297
0
  }
298
#if defined( HAVE_DEBUG_OUTPUT )
299
  if( libcnotify_verbose != 0 )
300
  {
301
    libcnotify_printf(
302
     "%s: URL record data:\n",
303
     function );
304
    libcnotify_print_data(
305
     data,
306
     data_size,
307
     0 );
308
  }
309
#endif
310
573
  if( memory_compare(
311
573
       data,
312
573
       "URL ",
313
573
       4 ) != 0 )
314
0
  {
315
0
    libcerror_error_set(
316
0
     error,
317
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
318
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
319
0
     "%s: unsupported signature.",
320
0
     function );
321
322
0
    goto on_error;
323
0
  }
324
573
  if( ( io_handle->major_version == 4 )
325
573
   && ( io_handle->minor_version == 7 ) )
326
3
  {
327
3
    byte_stream_copy_to_uint64_little_endian(
328
3
     ( (msiecf_url_record_header_v47_t *) data )->secondary_filetime,
329
3
     url_values->secondary_time );
330
331
3
    byte_stream_copy_to_uint64_little_endian(
332
3
     ( (msiecf_url_record_header_v47_t *) data )->primary_filetime,
333
3
     url_values->primary_time );
334
335
3
    byte_stream_copy_to_uint64_little_endian(
336
3
     ( (msiecf_url_record_header_v47_t *) data )->expiration_time,
337
3
     url_values->expiration_time );
338
339
3
    byte_stream_copy_to_uint32_little_endian(
340
3
     ( (msiecf_url_record_header_v47_t *) data )->cached_file_size,
341
3
     url_values->cached_file_size );
342
343
3
    byte_stream_copy_to_uint32_little_endian(
344
3
     ( (msiecf_url_record_header_v47_t *) data )->unknown_offset,
345
3
     unknown_offset );
346
347
3
    byte_stream_copy_to_uint32_little_endian(
348
3
     ( (msiecf_url_record_header_v47_t *) data )->location_offset,
349
3
     location_offset );
350
351
3
    url_values->cache_directory_index = ( (msiecf_url_record_header_v47_t *) data )->cache_directory_index;
352
353
3
    byte_stream_copy_to_uint32_little_endian(
354
3
     ( (msiecf_url_record_header_v47_t *) data )->filename_offset,
355
3
     filename_offset );
356
357
3
    byte_stream_copy_to_uint32_little_endian(
358
3
     ( (msiecf_url_record_header_v47_t *) data )->data_offset,
359
3
     url_data_offset );
360
361
3
    byte_stream_copy_to_uint32_little_endian(
362
3
     ( (msiecf_url_record_header_v47_t *) data )->data_size,
363
3
     url_data_size );
364
365
3
    byte_stream_copy_to_uint32_little_endian(
366
3
     ( (msiecf_url_record_header_v47_t *) data )->last_checked_time,
367
3
     url_values->last_checked_time );
368
369
3
    byte_stream_copy_to_uint32_little_endian(
370
3
     ( (msiecf_url_record_header_v47_t *) data )->number_of_hits,
371
3
     url_values->number_of_hits );
372
373
3
    byte_stream_copy_to_uint32_little_endian(
374
3
     ( (msiecf_url_record_header_v47_t *) data )->cache_entry_flags,
375
3
     cache_entry_flags );
376
3
  }
377
570
  else if( ( io_handle->major_version == 5 )
378
570
        && ( io_handle->minor_version == 2 ) )
379
570
  {
380
570
    byte_stream_copy_to_uint64_little_endian(
381
570
     ( (msiecf_url_record_header_v52_t *) data )->secondary_filetime,
382
570
     url_values->secondary_time );
383
384
570
    byte_stream_copy_to_uint64_little_endian(
385
570
     ( (msiecf_url_record_header_v52_t *) data )->primary_filetime,
386
570
     url_values->primary_time );
387
388
570
    byte_stream_copy_to_uint32_little_endian(
389
570
     ( (msiecf_url_record_header_v52_t *) data )->expiration_time,
390
570
     url_values->expiration_time );
391
392
570
    byte_stream_copy_to_uint32_little_endian(
393
570
     ( (msiecf_url_record_header_v52_t *) data )->cached_file_size,
394
570
     url_values->cached_file_size );
395
396
570
    byte_stream_copy_to_uint32_little_endian(
397
570
     ( (msiecf_url_record_header_v52_t *) data )->unknown_offset,
398
570
     unknown_offset );
399
400
570
    byte_stream_copy_to_uint32_little_endian(
401
570
     ( (msiecf_url_record_header_v52_t *) data )->location_offset,
402
570
     location_offset );
403
404
570
    url_values->cache_directory_index = ( (msiecf_url_record_header_v52_t *) data )->cache_directory_index;
405
406
570
    byte_stream_copy_to_uint32_little_endian(
407
570
     ( (msiecf_url_record_header_v52_t *) data )->filename_offset,
408
570
     filename_offset );
409
410
570
    byte_stream_copy_to_uint32_little_endian(
411
570
     ( (msiecf_url_record_header_v52_t *) data )->data_offset,
412
570
     url_data_offset );
413
414
570
    byte_stream_copy_to_uint32_little_endian(
415
570
     ( (msiecf_url_record_header_v52_t *) data )->data_size,
416
570
     url_data_size );
417
418
570
    byte_stream_copy_to_uint32_little_endian(
419
570
     ( (msiecf_url_record_header_v52_t *) data )->last_checked_time,
420
570
     url_values->last_checked_time );
421
422
570
    byte_stream_copy_to_uint32_little_endian(
423
570
     ( (msiecf_url_record_header_v52_t *) data )->number_of_hits,
424
570
     url_values->number_of_hits );
425
426
570
    byte_stream_copy_to_uint32_little_endian(
427
570
     ( (msiecf_url_record_header_v52_t *) data )->cache_entry_flags,
428
570
     cache_entry_flags );
429
570
  }
430
#if defined( HAVE_DEBUG_OUTPUT )
431
  if( libcnotify_verbose != 0 )
432
  {
433
    libcnotify_printf(
434
     "%s: signature\t\t\t\t: %c%c%c%c\n",
435
     function,
436
     data[ 0 ],
437
     data[ 1 ],
438
     data[ 2 ],
439
     data[ 3 ] );
440
441
    byte_stream_copy_to_uint32_little_endian(
442
     ( (msiecf_url_record_header_v47_t *) data )->number_of_blocks,
443
     value_32bit );
444
    libcnotify_printf(
445
     "%s: number of blocks\t\t\t: %" PRIu32 "\n",
446
     function,
447
     value_32bit );
448
449
    if( libmsiecf_debug_print_filetime_value(
450
         function,
451
         "secondary time\t\t\t\t",
452
         ( (msiecf_url_record_header_v47_t *) data )->secondary_filetime,
453
         8,
454
         LIBFDATETIME_ENDIAN_LITTLE,
455
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
456
         error ) != 1 )
457
    {
458
      libcerror_error_set(
459
       error,
460
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
461
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
462
       "%s: unable to print FILETIME value.",
463
       function );
464
465
      goto on_error;
466
    }
467
    if( libmsiecf_debug_print_filetime_value(
468
         function,
469
         "primary time\t\t\t\t",
470
         ( (msiecf_url_record_header_v47_t *) data )->primary_filetime,
471
         8,
472
         LIBFDATETIME_ENDIAN_LITTLE,
473
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
474
         error ) != 1 )
475
    {
476
      libcerror_error_set(
477
       error,
478
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
479
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
480
       "%s: unable to print FILETIME value.",
481
       function );
482
483
      goto on_error;
484
    }
485
    if( ( io_handle->major_version == 4 )
486
     && ( io_handle->minor_version == 7 ) )
487
    {
488
      if( libmsiecf_debug_print_filetime_value(
489
           function,
490
           "expiration time\t\t\t\t",
491
           ( (msiecf_url_record_header_v47_t *) data )->expiration_time,
492
           8,
493
           LIBFDATETIME_ENDIAN_LITTLE,
494
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
495
           error ) != 1 )
496
      {
497
        libcerror_error_set(
498
         error,
499
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
500
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
501
         "%s: unable to print FILETIME value.",
502
         function );
503
504
        goto on_error;
505
      }
506
    }
507
    else if( ( io_handle->major_version == 5 )
508
          && ( io_handle->minor_version == 2 ) )
509
    {
510
      if( libmsiecf_debug_print_fat_date_time_value(
511
           function,
512
           "expiration time\t\t\t\t",
513
           ( (msiecf_url_record_header_v52_t *) data )->expiration_time,
514
           4,
515
           LIBFDATETIME_ENDIAN_LITTLE,
516
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
517
           error ) != 1 )
518
      {
519
        libcerror_error_set(
520
         error,
521
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
522
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
523
         "%s: unable to print FAT date time value.",
524
         function );
525
526
        goto on_error;
527
      }
528
    }
529
    if( ( io_handle->major_version == 5 )
530
     && ( io_handle->minor_version == 2 ) )
531
    {
532
      byte_stream_copy_to_uint32_little_endian(
533
       ( (msiecf_url_record_header_v52_t *) data )->unknown1,
534
       value_32bit );
535
536
      libcnotify_printf(
537
       "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
538
       function,
539
       value_32bit );
540
    }
541
    libcnotify_printf(
542
     "%s: cached file size\t\t\t: %" PRIu32 " bytes\n",
543
     function,
544
     url_values->cached_file_size );
545
546
    if( ( io_handle->major_version == 4 )
547
     && ( io_handle->minor_version == 7 ) )
548
    {
549
      byte_stream_copy_to_uint32_little_endian(
550
       ( (msiecf_url_record_header_v47_t *) data )->unknown1,
551
       value_32bit );
552
553
      libcnotify_printf(
554
       "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
555
       function,
556
       value_32bit );
557
    }
558
    if( ( io_handle->major_version == 4 )
559
     && ( io_handle->minor_version == 7 ) )
560
    {
561
      byte_stream_copy_to_uint32_little_endian(
562
       ( (msiecf_url_record_header_v47_t *) data )->unknown3,
563
       value_32bit );
564
    }
565
    else if( ( io_handle->major_version == 5 )
566
          && ( io_handle->minor_version == 2 ) )
567
    {
568
      byte_stream_copy_to_uint32_little_endian(
569
       ( (msiecf_url_record_header_v52_t *) data )->unknown3,
570
       value_32bit );
571
    }
572
    libcnotify_printf(
573
     "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n",
574
     function,
575
     value_32bit );
576
577
    if( ( io_handle->major_version == 4 )
578
     && ( io_handle->minor_version == 7 ) )
579
    {
580
      byte_stream_copy_to_uint32_little_endian(
581
       ( (msiecf_url_record_header_v47_t *) data )->unknown4,
582
       value_32bit );
583
    }
584
    else if( ( io_handle->major_version == 5 )
585
          && ( io_handle->minor_version == 2 ) )
586
    {
587
      byte_stream_copy_to_uint32_little_endian(
588
       ( (msiecf_url_record_header_v52_t *) data )->unknown4,
589
       value_32bit );
590
    }
591
    libcnotify_printf(
592
     "%s: unknown4\t\t\t\t: 0x%08" PRIx32 "\n",
593
     function,
594
     value_32bit );
595
596
    if( ( io_handle->major_version == 4 )
597
     && ( io_handle->minor_version == 7 ) )
598
    {
599
      byte_stream_copy_to_uint32_little_endian(
600
       ( (msiecf_url_record_header_v47_t *) data )->non_releasable_time_delta,
601
       value_32bit );
602
    }
603
    else if( ( io_handle->major_version == 5 )
604
          && ( io_handle->minor_version == 2 ) )
605
    {
606
      byte_stream_copy_to_uint32_little_endian(
607
       ( (msiecf_url_record_header_v52_t *) data )->non_releasable_time_delta,
608
       value_32bit );
609
    }
610
    libcnotify_printf(
611
     "%s: non-releasable time delta\t\t: %" PRIu32 " seconds\n",
612
     function,
613
     value_32bit );
614
615
    libcnotify_printf(
616
     "%s: unknown offset\t\t\t\t: %" PRIu32 "\n",
617
     function,
618
     unknown_offset );
619
620
    libcnotify_printf(
621
     "%s: location offset\t\t\t\t: %" PRIu32 "\n",
622
     function,
623
     location_offset );
624
625
    libcnotify_printf(
626
     "%s: cache directory index\t\t\t: %" PRIu8 "\n",
627
     function,
628
     url_values->cache_directory_index );
629
630
    if( ( io_handle->major_version == 4 )
631
     && ( io_handle->minor_version == 7 ) )
632
    {
633
      libcnotify_printf(
634
       "%s: unknown6\t\t\t\t: 0x%02" PRIx8 " 0x%02" PRIx8 " 0x%02" PRIx8 "\n",
635
       function,
636
       ( (msiecf_url_record_header_v47_t *) data )->unknown6[ 0 ],
637
       ( (msiecf_url_record_header_v47_t *) data )->unknown6[ 1 ],
638
       ( (msiecf_url_record_header_v47_t *) data )->unknown6[ 2 ] );
639
    }
640
    else if( ( io_handle->major_version == 5 )
641
          && ( io_handle->minor_version == 2 ) )
642
    {
643
      libcnotify_printf(
644
       "%s: unknown6\t\t\t\t: 0x%02" PRIx8 " 0x%02" PRIx8 " 0x%02" PRIx8 "\n",
645
       function,
646
       ( (msiecf_url_record_header_v52_t *) data )->unknown6[ 0 ],
647
       ( (msiecf_url_record_header_v52_t *) data )->unknown6[ 1 ],
648
       ( (msiecf_url_record_header_v52_t *) data )->unknown6[ 2 ] );
649
    }
650
    libcnotify_printf(
651
     "%s: filename offset\t\t\t\t: %" PRIu32 "\n",
652
     function,
653
     filename_offset );
654
655
    libcnotify_printf(
656
     "%s: cache entry flags\t\t\t: 0x%08" PRIx32 "\n",
657
     function,
658
     cache_entry_flags );
659
    libmsiecf_debug_print_cache_entry_flags(
660
     cache_entry_flags );
661
    libcnotify_printf(
662
     "\n" );
663
664
    libcnotify_printf(
665
     "%s: data offset\t\t\t\t: %" PRIu32 "\n",
666
     function,
667
     url_data_offset );
668
    libcnotify_printf(
669
     "%s: data size\t\t\t\t: %" PRIu32 "\n",
670
     function,
671
     url_data_size );
672
673
    if( ( io_handle->major_version == 4 )
674
     && ( io_handle->minor_version == 7 ) )
675
    {
676
      byte_stream_copy_to_uint32_little_endian(
677
       ( (msiecf_url_record_header_v47_t *) data )->unknown8,
678
       value_32bit );
679
    }
680
    else if( ( io_handle->major_version == 5 )
681
          && ( io_handle->minor_version == 2 ) )
682
    {
683
      byte_stream_copy_to_uint32_little_endian(
684
       ( (msiecf_url_record_header_v52_t *) data )->unknown8,
685
       value_32bit );
686
    }
687
    libcnotify_printf(
688
     "%s: unknown8\t\t\t\t: 0x%08" PRIx32 "\n",
689
     function,
690
     value_32bit );
691
692
    if( ( io_handle->major_version == 4 )
693
     && ( io_handle->minor_version == 7 ) )
694
    {
695
      if( libmsiecf_debug_print_fat_date_time_value(
696
           function,
697
           "last checked time\t\t\t",
698
           ( (msiecf_url_record_header_v47_t *) data )->last_checked_time,
699
           4,
700
           LIBFDATETIME_ENDIAN_LITTLE,
701
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
702
           error ) != 1 )
703
      {
704
        libcerror_error_set(
705
         error,
706
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
707
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
708
         "%s: unable to print FAT date time value.",
709
         function );
710
711
        goto on_error;
712
      }
713
    }
714
    else if( ( io_handle->major_version == 5 )
715
          && ( io_handle->minor_version == 2 ) )
716
    {
717
      if( libmsiecf_debug_print_fat_date_time_value(
718
           function,
719
           "last checked time\t\t\t",
720
           ( (msiecf_url_record_header_v52_t *) data )->last_checked_time,
721
           4,
722
           LIBFDATETIME_ENDIAN_LITTLE,
723
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
724
           error ) != 1 )
725
      {
726
        libcerror_error_set(
727
         error,
728
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
729
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
730
         "%s: unable to print FAT date time value.",
731
         function );
732
733
        goto on_error;
734
      }
735
    }
736
    libcnotify_printf(
737
     "%s: number of hits\t\t\t\t: %" PRIu32 "\n",
738
     function,
739
     url_values->number_of_hits );
740
741
    if( ( io_handle->major_version == 4 )
742
     && ( io_handle->minor_version == 7 ) )
743
    {
744
      byte_stream_copy_to_uint32_little_endian(
745
       ( (msiecf_url_record_header_v47_t *) data )->unknown9,
746
       value_32bit );
747
    }
748
    else if( ( io_handle->major_version == 5 )
749
          && ( io_handle->minor_version == 2 ) )
750
    {
751
      byte_stream_copy_to_uint32_little_endian(
752
       ( (msiecf_url_record_header_v52_t *) data )->unknown9,
753
       value_32bit );
754
    }
755
    libcnotify_printf(
756
     "%s: unknown9\t\t\t\t: 0x%08" PRIx32 "\n",
757
     function,
758
     value_32bit );
759
760
    if( ( io_handle->major_version == 4 )
761
     && ( io_handle->minor_version == 7 ) )
762
    {
763
      if( libmsiecf_debug_print_fat_date_time_value(
764
           function,
765
           "unknown time\t\t\t\t",
766
           ( (msiecf_url_record_header_v47_t *) data )->unknown_time,
767
           4,
768
           LIBFDATETIME_ENDIAN_LITTLE,
769
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
770
           error ) != 1 )
771
      {
772
        libcerror_error_set(
773
         error,
774
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
775
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
776
         "%s: unable to print FAT date time value.",
777
         function );
778
779
        goto on_error;
780
      }
781
    }
782
    else if( ( io_handle->major_version == 5 )
783
          && ( io_handle->minor_version == 2 ) )
784
    {
785
      if( libmsiecf_debug_print_fat_date_time_value(
786
           function,
787
           "unknown time\t\t\t\t",
788
           ( (msiecf_url_record_header_v52_t *) data )->unknown_time,
789
           4,
790
           LIBFDATETIME_ENDIAN_LITTLE,
791
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
792
           error ) != 1 )
793
      {
794
        libcerror_error_set(
795
         error,
796
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
797
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
798
         "%s: unable to print FAT date time value.",
799
         function );
800
801
        goto on_error;
802
      }
803
    }
804
  }
805
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
806
807
573
  if( unknown_offset > 0 )
808
337
  {
809
337
    if( unknown_offset > data_size )
810
68
    {
811
68
      if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 )
812
68
      {
813
68
        libcerror_error_set(
814
68
         error,
815
68
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
816
68
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
817
68
         "%s: unknown offset exceeds URL record data.",
818
68
         function );
819
820
68
        goto on_error;
821
68
      }
822
0
      else
823
0
      {
824
0
        memory_free(
825
0
         data );
826
827
0
        return( 1 );
828
0
      }
829
68
    }
830
#if defined( HAVE_DEBUG_OUTPUT )
831
    if( libcnotify_verbose != 0 )
832
    {
833
      libcnotify_printf(
834
       "%s: unknown:\n",
835
       function );
836
      libcnotify_print_data(
837
       &( data[ unknown_offset ] ),
838
       8,
839
       0 );
840
    }
841
#endif
842
337
  }
843
505
  if( location_offset > 0 )
844
495
  {
845
495
    if( location_offset > data_size )
846
63
    {
847
63
      if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 )
848
63
      {
849
63
        libcerror_error_set(
850
63
         error,
851
63
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
852
63
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
853
63
         "%s: location offset exceeds size of URL record data.",
854
63
         function );
855
856
63
        return( -1 );
857
63
      }
858
63
    }
859
432
    else
860
432
    {
861
432
      if( libfvalue_value_type_initialize(
862
432
           &( url_values->location ),
863
432
           LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM,
864
432
           error ) != 1 )
865
0
      {
866
0
        libcerror_error_set(
867
0
         error,
868
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
869
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
870
0
         "%s: unable to create location value.",
871
0
         function );
872
873
0
        goto on_error;
874
0
      }
875
432
      value_size = libfvalue_value_type_set_data_string(
876
432
                    url_values->location,
877
432
                    &( data[ location_offset ] ),
878
432
                    data_size - location_offset,
879
432
                    io_handle->ascii_codepage,
880
432
                    LIBFVALUE_VALUE_DATA_FLAG_MANAGED,
881
432
                    error );
882
883
432
      if( value_size == -1 )
884
0
      {
885
0
        libcerror_error_set(
886
0
         error,
887
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
888
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
889
0
         "%s: unable to set data of location value.",
890
0
         function );
891
892
0
        goto on_error;
893
0
      }
894
#if defined( HAVE_DEBUG_OUTPUT )
895
      if( libcnotify_verbose != 0 )
896
      {
897
        libcnotify_printf(
898
         "%s: location\t\t\t\t: ",
899
         function );
900
901
        if( libfvalue_value_print(
902
             url_values->location,
903
             0,
904
             0,
905
             error ) != 1 )
906
        {
907
          libcerror_error_set(
908
           error,
909
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
910
           LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
911
           "%s: unable to print location value.",
912
           function );
913
914
          goto on_error;
915
        }
916
        libcnotify_printf(
917
         "\n" );
918
919
        if( libmsiecf_hash_calculate(
920
             &value_32bit,
921
             &( data[ location_offset ] ),
922
             data_size - location_offset,
923
             error ) != 1 )
924
        {
925
          libcerror_error_set(
926
           error,
927
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
928
           LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
929
           "%s: unable to calculate location hash.",
930
           function );
931
932
          goto on_error;
933
        }
934
        libcnotify_printf(
935
         "%s: hash value\t\t\t\t: 0x%08" PRIx32 "\n",
936
         function,
937
         value_32bit );
938
      }
939
#endif
940
432
      if( ( data[ location_offset + value_size - 1 ] != 0 )
941
432
       && ( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) )
942
2
      {
943
2
        libcerror_error_set(
944
2
         error,
945
2
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
946
2
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
947
2
         "%s: unsupported unterminated location string.",
948
2
         function );
949
950
2
        goto on_error;
951
2
      }
952
430
      if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED )
953
430
      {
954
430
        if( value_size >= 18 )
955
382
        {
956
382
          if( ( data[ location_offset ] == (uint8_t) ':' )
957
382
           && ( data[ location_offset + 1 ] >= (uint8_t) '0' )
958
382
           && ( data[ location_offset + 1 ] <= (uint8_t) '9' )
959
382
           && ( data[ location_offset + 2 ] >= (uint8_t) '0' )
960
382
           && ( data[ location_offset + 2 ] <= (uint8_t) '9' )
961
382
           && ( data[ location_offset + 3 ] >= (uint8_t) '0' )
962
382
           && ( data[ location_offset + 3 ] <= (uint8_t) '9' )
963
382
           && ( data[ location_offset + 4 ] >= (uint8_t) '0' )
964
382
           && ( data[ location_offset + 4 ] <= (uint8_t) '9' )
965
382
           && ( data[ location_offset + 5 ] >= (uint8_t) '0' )
966
382
           && ( data[ location_offset + 5 ] <= (uint8_t) '9' )
967
382
           && ( data[ location_offset + 6 ] >= (uint8_t) '0' )
968
382
           && ( data[ location_offset + 6 ] <= (uint8_t) '9' )
969
382
           && ( data[ location_offset + 7 ] >= (uint8_t) '0' )
970
382
           && ( data[ location_offset + 7 ] <= (uint8_t) '9' )
971
382
           && ( data[ location_offset + 8 ] >= (uint8_t) '0' )
972
382
           && ( data[ location_offset + 8 ] <= (uint8_t) '9' )
973
382
           && ( data[ location_offset + 9 ] >= (uint8_t) '0' )
974
382
           && ( data[ location_offset + 9 ] <= (uint8_t) '9' )
975
382
           && ( data[ location_offset + 10 ] >= (uint8_t) '0' )
976
382
           && ( data[ location_offset + 10 ] <= (uint8_t) '9' )
977
382
           && ( data[ location_offset + 11 ] >= (uint8_t) '0' )
978
382
           && ( data[ location_offset + 11 ] <= (uint8_t) '9' )
979
382
           && ( data[ location_offset + 12 ] >= (uint8_t) '0' )
980
382
           && ( data[ location_offset + 12 ] <= (uint8_t) '9' )
981
382
           && ( data[ location_offset + 13 ] >= (uint8_t) '0' )
982
382
           && ( data[ location_offset + 13 ] <= (uint8_t) '9' )
983
382
           && ( data[ location_offset + 14 ] >= (uint8_t) '0' )
984
382
           && ( data[ location_offset + 14 ] <= (uint8_t) '9' )
985
382
           && ( data[ location_offset + 15 ] >= (uint8_t) '0' )
986
382
           && ( data[ location_offset + 15 ] <= (uint8_t) '9' )
987
382
           && ( data[ location_offset + 16 ] >= (uint8_t) '0' )
988
382
           && ( data[ location_offset + 16 ] <= (uint8_t) '9' )
989
382
           && ( data[ location_offset + 17 ] == (uint8_t) ':' ) )
990
66
          {
991
66
            first_year  = (uint16_t) data[ location_offset + 1 ] - (uint8_t) '0';
992
66
            first_year *= 10;
993
66
            first_year += (uint16_t) data[ location_offset + 2 ] - (uint8_t) '0';
994
66
            first_year *= 10;
995
66
            first_year += (uint16_t) data[ location_offset + 3 ] - (uint8_t) '0';
996
66
            first_year *= 10;
997
66
            first_year += (uint16_t) data[ location_offset + 4 ] - (uint8_t) '0';
998
999
66
            first_month  = data[ location_offset + 5 ] - (uint8_t) '0';
1000
66
            first_month *= 10;
1001
66
            first_month += data[ location_offset + 6 ] - (uint8_t) '0';
1002
1003
66
            first_day_of_month  = data[ location_offset + 7 ] - (uint8_t) '0';
1004
66
            first_day_of_month *= 10;
1005
66
            first_day_of_month += data[ location_offset + 8 ] - (uint8_t) '0';
1006
1007
66
            second_year  = (uint16_t) data[ location_offset + 9 ] - (uint8_t) '0';
1008
66
            second_year *= 10;
1009
66
            second_year += (uint16_t) data[ location_offset + 10 ] - (uint8_t) '0';
1010
66
            second_year *= 10;
1011
66
            second_year += (uint16_t) data[ location_offset + 11 ] - (uint8_t) '0';
1012
66
            second_year *= 10;
1013
66
            second_year += (uint16_t) data[ location_offset + 12 ] - (uint8_t) '0';
1014
1015
66
            second_month  = data[ location_offset + 13 ] - (uint8_t) '0';
1016
66
            second_month *= 10;
1017
66
            second_month += data[ location_offset + 14 ] - (uint8_t) '0';
1018
1019
66
            second_day_of_month  = data[ location_offset + 15 ] - (uint8_t) '0';
1020
66
            second_day_of_month *= 10;
1021
66
            second_day_of_month += data[ location_offset + 16 ] - (uint8_t) '0';
1022
1023
66
            number_of_days = 0;
1024
1025
66
            if( first_year == second_year )
1026
42
            {
1027
42
              if( first_month == second_month )
1028
10
              {
1029
10
                if( first_day_of_month < second_day_of_month )
1030
2
                {
1031
2
                  number_of_days = second_day_of_month - first_day_of_month;
1032
2
                }
1033
10
              }
1034
32
              else if( ( first_month + 1 ) == second_month )
1035
23
              {
1036
23
                switch( first_month )
1037
23
                {
1038
1
                  case 3:
1039
2
                  case 5:
1040
3
                  case 7:
1041
4
                  case 8:
1042
5
                  case 10:
1043
6
                  case 12:
1044
6
                    number_of_days = ( 31 + second_day_of_month ) - first_day_of_month;
1045
6
                    break;
1046
1047
12
                  case 2:
1048
12
                    if( ( ( ( first_year % 4 ) == 0 )
1049
12
                      &&  ( ( first_year % 100 ) != 0 ) )
1050
12
                     || ( ( first_year % 400 ) == 0 ) )
1051
5
                    {
1052
5
                      number_of_days = ( 29 + second_day_of_month ) - first_day_of_month;
1053
5
                    }
1054
7
                    else
1055
7
                    {
1056
7
                      number_of_days = ( 28 + second_day_of_month ) - first_day_of_month;
1057
7
                    }
1058
12
                    break;
1059
1060
1
                  case 4:
1061
2
                  case 6:
1062
3
                  case 9:
1063
4
                  case 11:
1064
4
                    number_of_days = ( 30 + second_day_of_month ) - first_day_of_month;
1065
4
                    break;
1066
23
                }
1067
23
              }
1068
42
            }
1069
24
            else if( ( first_year + 1 ) == second_year )
1070
8
            {
1071
8
              if( ( first_month == 12 )
1072
8
               && ( second_month == 1 ) )
1073
1
              {
1074
1
                number_of_days = ( 31 + second_day_of_month ) - first_day_of_month;
1075
1
              }
1076
8
            }
1077
66
            if( number_of_days == 1 )
1078
4
            {
1079
4
              url_values->type = LIBMSIECF_URL_ITEM_TYPE_HISTORY_DAILY;
1080
4
            }
1081
62
            else if( number_of_days == 7 )
1082
2
            {
1083
2
              url_values->type = LIBMSIECF_URL_ITEM_TYPE_HISTORY_WEEKLY;
1084
2
            }
1085
66
          }
1086
382
        }
1087
430
      }
1088
430
      if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED )
1089
424
      {
1090
424
        if( value_size >= 11 )
1091
400
        {
1092
400
          if( memory_compare(
1093
400
               &( data[ location_offset ] ),
1094
400
               "iedownload:",
1095
400
               11 ) == 0 )
1096
2
          {
1097
2
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_DOWNLOAD;
1098
2
          }
1099
400
        }
1100
424
      }
1101
430
      if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED )
1102
422
      {
1103
422
        if( value_size >= 9 )
1104
403
        {
1105
403
          if( memory_compare(
1106
403
               &( data[ location_offset ] ),
1107
403
               "DOMStore:",
1108
403
               9 ) == 0 )
1109
2
          {
1110
2
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_DOM_STORE;
1111
2
          }
1112
401
          else if( memory_compare(
1113
401
                    &( data[ location_offset ] ),
1114
401
                    "feedplat:",
1115
401
                    9 ) == 0 )
1116
2
          {
1117
2
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_RSS_FEED;
1118
2
          }
1119
399
          else if( memory_compare(
1120
399
                    &( data[ location_offset ] ),
1121
399
                    "iecompat:",
1122
399
                    9 ) == 0 )
1123
2
          {
1124
2
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_COMPATIBILITY;
1125
2
          }
1126
397
          else if( memory_compare(
1127
397
                    &( data[ location_offset ] ),
1128
397
                    "PrivacIE:",
1129
397
                    9 ) == 0 )
1130
2
          {
1131
2
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_INPRIVATE_FILTERING;
1132
2
          }
1133
395
          else if( memory_compare(
1134
395
                    &( data[ location_offset ] ),
1135
395
                    "userdata:",
1136
395
                    9 ) == 0 )
1137
1
          {
1138
1
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_USER_DATA;
1139
1
          }
1140
403
        }
1141
422
      }
1142
430
      if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED )
1143
413
      {
1144
413
        if( value_size >= 8 )
1145
396
        {
1146
396
          if( memory_compare(
1147
396
               &( data[ location_offset ] ),
1148
396
               "Visited:",
1149
396
               8 ) == 0 )
1150
1
          {
1151
1
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_HISTORY;
1152
1
          }
1153
396
        }
1154
413
      }
1155
430
      if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED )
1156
412
      {
1157
412
        if( value_size >= 7 )
1158
396
        {
1159
396
          if( memory_compare(
1160
396
               &( data[ location_offset ] ),
1161
396
               "Cookie:",
1162
396
               7 ) == 0 )
1163
1
          {
1164
1
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_COOKIE;
1165
1
          }
1166
396
        }
1167
412
      }
1168
430
      if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED )
1169
411
      {
1170
411
        if( value_size >= 6 )
1171
398
        {
1172
398
          if( memory_compare(
1173
398
               &( data[ location_offset ] ),
1174
398
               "ietld:",
1175
398
               6 ) == 0 )
1176
3
          {
1177
3
            url_values->type = LIBMSIECF_URL_ITEM_TYPE_TLD;
1178
3
          }
1179
398
        }
1180
411
      }
1181
430
      if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_UNDEFINED )
1182
408
      {
1183
408
        url_values->type = LIBMSIECF_URL_ITEM_TYPE_CACHE;
1184
1185
/* TODO way to determine unknown
1186
        url_values->type = LIBMSIECF_URL_ITEM_TYPE_UNKNOWN;
1187
*/
1188
408
      }
1189
430
    }
1190
495
  }
1191
440
  if( filename_offset > 0 )
1192
344
  {
1193
344
    if( filename_offset > data_size )
1194
181
    {
1195
181
      if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 )
1196
181
      {
1197
181
        libcerror_error_set(
1198
181
         error,
1199
181
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1200
181
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1201
181
         "%s: filename offset exceeds size of URL record data.",
1202
181
         function );
1203
1204
181
        goto on_error;
1205
181
      }
1206
181
    }
1207
163
    else
1208
163
    {
1209
163
      if( libfvalue_value_type_initialize(
1210
163
           &( url_values->filename ),
1211
163
           LIBFVALUE_VALUE_TYPE_STRING_BYTE_STREAM,
1212
163
           error ) != 1 )
1213
0
      {
1214
0
        libcerror_error_set(
1215
0
         error,
1216
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1217
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1218
0
         "%s: unable to create filename value.",
1219
0
         function );
1220
1221
0
        goto on_error;
1222
0
      }
1223
163
      value_size = libfvalue_value_type_set_data_string(
1224
163
                    url_values->filename,
1225
163
                    &( data[ filename_offset ] ),
1226
163
                    data_size - filename_offset,
1227
163
                    io_handle->ascii_codepage,
1228
163
                    LIBFVALUE_VALUE_DATA_FLAG_MANAGED,
1229
163
                    error );
1230
1231
163
      if( value_size == -1 )
1232
0
      {
1233
0
        libcerror_error_set(
1234
0
         error,
1235
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1236
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1237
0
         "%s: unable to set data of filename value.",
1238
0
         function );
1239
1240
0
        goto on_error;
1241
0
      }
1242
#if defined( HAVE_DEBUG_OUTPUT )
1243
      if( libcnotify_verbose != 0 )
1244
      {
1245
        libcnotify_printf(
1246
         "%s: filename\t\t\t\t: ",
1247
         function );
1248
1249
        if( libfvalue_value_print(
1250
             url_values->filename,
1251
             0,
1252
             0,
1253
             error ) != 1 )
1254
        {
1255
          libcerror_error_set(
1256
           error,
1257
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1258
           LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
1259
           "%s: unable to print filename value.",
1260
           function );
1261
1262
          goto on_error;
1263
        }
1264
        libcnotify_printf(
1265
         "\n" );
1266
      }
1267
#endif
1268
163
      if( ( data[ filename_offset + value_size - 1 ] != 0 )
1269
163
       && ( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 ) )
1270
18
      {
1271
18
        libcerror_error_set(
1272
18
         error,
1273
18
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1274
18
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1275
18
         "%s: unsupported unterminated filename string.",
1276
18
         function );
1277
1278
18
        goto on_error;
1279
18
      }
1280
163
    }
1281
344
  }
1282
241
  if( url_data_offset > 0 )
1283
236
  {
1284
236
    if( url_data_offset > data_size )
1285
128
    {
1286
128
      if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 )
1287
128
      {
1288
128
        libcerror_error_set(
1289
128
         error,
1290
128
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291
128
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1292
128
         "%s: data offset exceeds size of URL record data.",
1293
128
         function );
1294
1295
128
        goto on_error;
1296
128
      }
1297
128
    }
1298
108
    else
1299
108
    {
1300
108
      if( ( url_data_offset + url_data_size ) > data_size )
1301
53
      {
1302
53
        if( ( item_flags & LIBMSIECF_ITEM_FLAG_PARTIAL ) == 0 )
1303
53
        {
1304
53
          libcerror_error_set(
1305
53
           error,
1306
53
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1307
53
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1308
53
           "%s: data size exceeds size of URL record data.",
1309
53
           function );
1310
1311
53
          goto on_error;
1312
53
        }
1313
0
        else
1314
0
        {
1315
0
          url_data_size = data_size - url_data_offset;
1316
0
        }
1317
53
      }
1318
55
      if( ( url_data_size == 0 )
1319
55
       || ( url_data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1320
22
      {
1321
22
        libcerror_error_set(
1322
22
         error,
1323
22
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1324
22
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1325
22
         "%s: invalid URL data size value exceeds out of bounds.",
1326
22
         function );
1327
1328
22
        goto on_error;
1329
22
      }
1330
33
      url_values->data = (uint8_t *) memory_allocate(
1331
33
                                      sizeof( uint8_t ) * url_data_size );
1332
1333
33
      if( url_values->data == NULL )
1334
0
      {
1335
0
        libcerror_error_set(
1336
0
         error,
1337
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1338
0
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1339
0
         "%s: unable to create data.",
1340
0
         function );
1341
1342
0
        goto on_error;
1343
0
      }
1344
33
      url_values->data_size = (size_t) url_data_size;
1345
1346
33
      if( memory_copy(
1347
33
           url_values->data,
1348
33
           &( data[ url_data_offset ] ),
1349
33
           url_values->data_size ) == NULL )
1350
0
      {
1351
0
        libcerror_error_set(
1352
0
         error,
1353
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1354
0
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1355
0
         "%s: unable to copy data.",
1356
0
         function );
1357
1358
0
        goto on_error;
1359
0
      }
1360
#if defined( HAVE_DEBUG_OUTPUT )
1361
      if( libcnotify_verbose != 0 )
1362
      {
1363
        libcnotify_printf(
1364
         "%s: data:\n",
1365
         function );
1366
        libcnotify_print_data(
1367
         &( data[ url_data_offset ] ),
1368
         url_data_size,
1369
         0 );
1370
1371
        if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_CACHE )
1372
        {
1373
          /* The data string in not necessarily terminated by an end-of-string character
1374
           */
1375
          libcnotify_printf(
1376
           "%s: data string\t\t\t\t: ",
1377
           function );
1378
1379
          for( string_index = 0;
1380
               string_index < url_data_size;
1381
               string_index++ )
1382
          {
1383
            libcnotify_printf(
1384
             "%c",
1385
             data[ url_data_offset + string_index ] );
1386
          }
1387
          libcnotify_printf(
1388
           "\n" );
1389
        }
1390
        else if( url_values->type == LIBMSIECF_URL_ITEM_TYPE_HISTORY )
1391
        {
1392
          visited_entry_data = &( data[ url_data_offset ] );
1393
1394
          do
1395
          {
1396
            visited_entry_index++;
1397
1398
            byte_stream_copy_to_uint16_little_endian(
1399
             visited_entry_data,
1400
             value_16bit );
1401
1402
            visited_entry_data += 2;
1403
1404
            libcnotify_printf(
1405
             "%s: data entry: %02d size\t\t\t\t: %" PRIu16 "\n",
1406
             function,
1407
             visited_entry_index,
1408
             value_16bit );
1409
1410
            libcnotify_printf(
1411
             "%s: data entry: %02d type\t\t\t\t: 0x%02" PRIx8 " (%s : %s)\n",
1412
             function,
1413
             visited_entry_index,
1414
             visited_entry_data[ 0 ],
1415
             libmsiecf_property_type_get_identifier(
1416
              NULL,
1417
              (uint32_t) visited_entry_data[ 0 ],
1418
              (uint32_t) visited_entry_data[ 1 ] ),
1419
             libmsiecf_property_type_get_description(
1420
              NULL,
1421
              (uint32_t) visited_entry_data[ 0 ],
1422
              (uint32_t) visited_entry_data[ 1 ] ) );
1423
1424
            libcnotify_printf(
1425
             "%s: data entry: %02d value type\t\t\t: 0x%02" PRIx8 " (%s : %s)\n",
1426
             function,
1427
             visited_entry_index,
1428
             visited_entry_data[ 1 ],
1429
             libfole_value_type_get_identifier(
1430
              (uint32_t) visited_entry_data[ 1 ] ),
1431
             libfole_value_type_get_description(
1432
              (uint32_t) visited_entry_data[ 1 ] ) );
1433
1434
            visited_entry_data += 2;
1435
1436
            if( value_16bit > 4 )
1437
            {
1438
              value_16bit -= 4;
1439
1440
              libcnotify_printf(
1441
               "%s: data entry: %02d value:\n",
1442
               function,
1443
               visited_entry_index );
1444
              libcnotify_print_data(
1445
               visited_entry_data,
1446
               value_16bit,
1447
               0 );
1448
1449
              visited_entry_data += value_16bit;
1450
            }
1451
          }
1452
          while( value_16bit > 0 );
1453
        }
1454
      }
1455
#endif
1456
33
    }
1457
236
  }
1458
#if defined( HAVE_DEBUG_OUTPUT )
1459
  if( libcnotify_verbose != 0 )
1460
  {
1461
    libcnotify_printf(
1462
     "\n" );
1463
  }
1464
#endif
1465
#if defined( HAVE_VERBOSE_OUTPUT )
1466
  switch( url_values->type )
1467
  {
1468
    case LIBMSIECF_URL_ITEM_TYPE_COOKIE:
1469
      if ( ( cache_entry_flags & LIBMSIECF_CACHE_ENTRY_FLAG_COOKIE ) == 0 )
1470
      {
1471
        libcnotify_printf(
1472
         "%s: detected type cookie but corresponding cache entry flag (COOKIE_CACHE_ENTRY) is not set.\n",
1473
         function );
1474
      }
1475
      break;
1476
1477
    case LIBMSIECF_URL_ITEM_TYPE_HISTORY:
1478
      if ( ( cache_entry_flags & LIBMSIECF_CACHE_ENTRY_FLAG_URLHISTORY ) == 0 )
1479
      {
1480
        libcnotify_printf(
1481
         "%s: detected type history but corresponding cache entry flag (URLHISTORY_CACHE_ENTRY) is not set.\n",
1482
         function );
1483
      }
1484
      break;
1485
1486
    case LIBMSIECF_URL_ITEM_TYPE_HISTORY_DAILY:
1487
    case LIBMSIECF_URL_ITEM_TYPE_HISTORY_WEEKLY:
1488
      if ( ( cache_entry_flags & LIBMSIECF_CACHE_ENTRY_FLAG_URLHISTORY ) == 0 )
1489
      {
1490
        libcnotify_printf(
1491
         "%s: detected type history periodic but corresponding cache entry flag (URLHISTORY_CACHE_ENTRY) is not set.\n",
1492
         function );
1493
      }
1494
      break;
1495
  }
1496
#endif /* defined( HAVE_VERBOSE_OUTPUT ) */
1497
1498
38
  return( 1 );
1499
1500
472
on_error:
1501
/* TODO clean up */
1502
472
  return( -1 );
1503
241
}
1504
1505
/* Reads the URL values from an URL record
1506
 * Returns 1 if successful or -1 on error
1507
 */
1508
int libmsiecf_url_values_read_file_io_handle(
1509
     libmsiecf_url_values_t *url_values,
1510
     libmsiecf_io_handle_t *io_handle,
1511
     libbfio_handle_t *file_io_handle,
1512
     off64_t url_record_offset,
1513
     size32_t record_size,
1514
     uint8_t item_flags,
1515
     libcerror_error_t **error )
1516
600
{
1517
600
  uint8_t *record_data  = NULL;
1518
600
  static char *function = "libmsiecf_url_values_read_file_io_handle";
1519
600
  ssize_t read_count    = 0;
1520
1521
600
  if( url_values == NULL )
1522
0
  {
1523
0
    libcerror_error_set(
1524
0
     error,
1525
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1526
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1527
0
     "%s: invalid URL values.",
1528
0
     function );
1529
1530
0
    return( -1 );
1531
0
  }
1532
600
  if( record_size > (size32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
1533
2
  {
1534
2
    libcerror_error_set(
1535
2
     error,
1536
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1537
2
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1538
2
     "%s: invalid record size value exceeds maximum allocation size.",
1539
2
     function );
1540
1541
2
    return( -1 );
1542
2
  }
1543
598
  if( ( record_size == 0 )
1544
598
   || ( ( record_size % 8 ) != 0 ) )
1545
0
  {
1546
0
    libcerror_error_set(
1547
0
     error,
1548
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1549
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1550
0
     "%s: unsupported record size.",
1551
0
     function );
1552
1553
0
    return( -1 );
1554
0
  }
1555
  /* Add one block for tainted records
1556
   */
1557
598
  if( ( item_flags & LIBMSIECF_ITEM_FLAG_TAINTED ) != 0 )
1558
76
  {
1559
76
    record_size += LIBMSIECF_DEFAULT_BLOCK_SIZE;
1560
76
  }
1561
598
  record_data = (uint8_t *) memory_allocate(
1562
598
                             record_size );
1563
1564
598
  if( record_data == NULL )
1565
0
  {
1566
0
    libcerror_error_set(
1567
0
     error,
1568
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1569
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1570
0
     "%s: unable to create URL record data.",
1571
0
     function );
1572
1573
0
    goto on_error;
1574
0
  }
1575
#if defined( HAVE_DEBUG_OUTPUT )
1576
  if( libcnotify_verbose != 0 )
1577
  {
1578
    libcnotify_printf(
1579
     "%s: reading URL record at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
1580
     function,
1581
     url_record_offset,
1582
     url_record_offset );
1583
  }
1584
#endif
1585
598
  read_count = libbfio_handle_read_buffer_at_offset(
1586
598
                file_io_handle,
1587
598
                record_data,
1588
598
                record_size,
1589
598
                url_record_offset,
1590
598
                error );
1591
1592
598
  if( read_count != (ssize_t) record_size )
1593
25
  {
1594
25
    libcerror_error_set(
1595
25
     error,
1596
25
     LIBCERROR_ERROR_DOMAIN_IO,
1597
25
     LIBCERROR_IO_ERROR_READ_FAILED,
1598
25
     "%s: unable to read URL record data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1599
25
     function,
1600
25
     url_record_offset,
1601
25
     url_record_offset );
1602
1603
25
    goto on_error;
1604
25
  }
1605
573
  if( libmsiecf_url_values_read_data(
1606
573
       url_values,
1607
573
       io_handle,
1608
573
       record_data,
1609
573
       (size_t) record_size,
1610
573
       item_flags,
1611
573
       error ) != 1 )
1612
535
  {
1613
535
    libcerror_error_set(
1614
535
     error,
1615
535
     LIBCERROR_ERROR_DOMAIN_IO,
1616
535
     LIBCERROR_IO_ERROR_READ_FAILED,
1617
535
     "%s: unable to read URL record.",
1618
535
     function );
1619
1620
535
    goto on_error;
1621
535
  }
1622
38
  memory_free(
1623
38
   record_data );
1624
1625
38
  record_data = NULL;
1626
1627
38
  return( 1 );
1628
1629
560
on_error:
1630
560
  if( record_data != NULL )
1631
560
  {
1632
560
    memory_free(
1633
560
     record_data );
1634
560
  }
1635
560
  return( -1 );
1636
573
}
1637