dfindexeddb 20241105__py3-none-any.whl → 20251109__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. dfindexeddb/indexeddb/chromium/blink.py +116 -74
  2. dfindexeddb/indexeddb/chromium/definitions.py +148 -125
  3. dfindexeddb/indexeddb/chromium/record.py +426 -324
  4. dfindexeddb/indexeddb/chromium/v8.py +100 -78
  5. dfindexeddb/indexeddb/cli.py +122 -118
  6. dfindexeddb/indexeddb/firefox/definitions.py +7 -4
  7. dfindexeddb/indexeddb/firefox/gecko.py +98 -74
  8. dfindexeddb/indexeddb/firefox/record.py +66 -24
  9. dfindexeddb/indexeddb/safari/definitions.py +5 -3
  10. dfindexeddb/indexeddb/safari/record.py +68 -51
  11. dfindexeddb/indexeddb/safari/webkit.py +85 -71
  12. dfindexeddb/indexeddb/types.py +4 -1
  13. dfindexeddb/leveldb/cli.py +146 -138
  14. dfindexeddb/leveldb/definitions.py +6 -2
  15. dfindexeddb/leveldb/descriptor.py +70 -56
  16. dfindexeddb/leveldb/ldb.py +39 -33
  17. dfindexeddb/leveldb/log.py +41 -30
  18. dfindexeddb/leveldb/plugins/chrome_notifications.py +30 -18
  19. dfindexeddb/leveldb/plugins/interface.py +5 -6
  20. dfindexeddb/leveldb/plugins/manager.py +10 -9
  21. dfindexeddb/leveldb/record.py +71 -62
  22. dfindexeddb/leveldb/utils.py +21 -13
  23. dfindexeddb/utils.py +36 -31
  24. dfindexeddb/version.py +2 -2
  25. dfindexeddb-20251109.dist-info/METADATA +222 -0
  26. dfindexeddb-20251109.dist-info/RECORD +40 -0
  27. {dfindexeddb-20241105.dist-info → dfindexeddb-20251109.dist-info}/WHEEL +1 -1
  28. dfindexeddb-20241105.dist-info/AUTHORS +0 -12
  29. dfindexeddb-20241105.dist-info/METADATA +0 -424
  30. dfindexeddb-20241105.dist-info/RECORD +0 -41
  31. {dfindexeddb-20241105.dist-info → dfindexeddb-20251109.dist-info}/entry_points.txt +0 -0
  32. {dfindexeddb-20241105.dist-info → dfindexeddb-20251109.dist-info/licenses}/LICENSE +0 -0
  33. {dfindexeddb-20241105.dist-info → dfindexeddb-20251109.dist-info}/top_level.txt +0 -0
@@ -15,28 +15,31 @@
15
15
  """Parses Chromium IndexedDb structures."""
16
16
  from __future__ import annotations
17
17
 
18
- from dataclasses import dataclass, field
19
- from datetime import datetime
20
18
  import io
21
19
  import pathlib
22
20
  import sys
23
21
  import traceback
24
- from typing import Any, BinaryIO, Generator, Optional, Tuple, Type, TypeVar, \
25
- Union
26
-
27
- import snappy
22
+ from dataclasses import dataclass, field
23
+ from datetime import datetime
24
+ from typing import (
25
+ Any,
26
+ BinaryIO,
27
+ Generator,
28
+ Optional,
29
+ Tuple,
30
+ Type,
31
+ TypeVar,
32
+ Union,
33
+ )
28
34
 
29
35
  from dfindexeddb import errors
30
- from dfindexeddb.indexeddb.chromium import blink
31
- from dfindexeddb.indexeddb.chromium import definitions
32
- from dfindexeddb.leveldb import record
33
- from dfindexeddb.leveldb import utils
34
-
36
+ from dfindexeddb.indexeddb.chromium import blink, definitions
37
+ from dfindexeddb.leveldb import record, utils
35
38
 
36
- T = TypeVar('T')
39
+ T = TypeVar("T")
37
40
 
38
41
 
39
- @dataclass
42
+ @dataclass(frozen=True)
40
43
  class KeyPrefix(utils.FromDecoderMixin):
41
44
  """The IndexedDB key prefix.
42
45
 
@@ -46,6 +49,7 @@ class KeyPrefix(utils.FromDecoderMixin):
46
49
  object_store_id: the object store ID.
47
50
  index_id: the index ID.
48
51
  """
52
+
49
53
  offset: int = field(compare=False)
50
54
  database_id: int
51
55
  object_store_id: int
@@ -53,9 +57,7 @@ class KeyPrefix(utils.FromDecoderMixin):
53
57
 
54
58
  @classmethod
55
59
  def FromDecoder(
56
- cls,
57
- decoder: utils.LevelDBDecoder,
58
- base_offset: int = 0
60
+ cls, decoder: utils.LevelDBDecoder, base_offset: int = 0
59
61
  ) -> KeyPrefix:
60
62
  """Decodes a KeyPrefix from the current position of a LevelDBDecoder.
61
63
 
@@ -77,23 +79,24 @@ class KeyPrefix(utils.FromDecoderMixin):
77
79
  index_id_length = (raw_prefix[0] & 0x03) + 1
78
80
 
79
81
  if database_id_length < 1 or database_id_length > 8:
80
- raise errors.ParserError('Invalid database ID length')
82
+ raise errors.ParserError("Invalid database ID length")
81
83
 
82
84
  if object_store_id_length < 1 or object_store_id_length > 8:
83
- raise errors.ParserError('Invalid object store ID length')
85
+ raise errors.ParserError("Invalid object store ID length")
84
86
 
85
87
  if index_id_length < 1 or index_id_length > 4:
86
- raise errors.ParserError('Invalid index ID length')
88
+ raise errors.ParserError("Invalid index ID length")
87
89
 
88
- _, database_id = decoder.DecodeInt(database_id_length)
89
- _, object_store_id = decoder.DecodeInt(object_store_id_length)
90
- _, index_id = decoder.DecodeInt(index_id_length)
90
+ _, database_id = decoder.DecodeInt(database_id_length, signed=False)
91
+ _, object_store_id = decoder.DecodeInt(object_store_id_length, signed=False)
92
+ _, index_id = decoder.DecodeInt(index_id_length, signed=False)
91
93
 
92
94
  return cls(
93
95
  offset=base_offset + offset,
94
96
  database_id=database_id,
95
97
  object_store_id=object_store_id,
96
- index_id=index_id)
98
+ index_id=index_id,
99
+ )
97
100
 
98
101
  def GetKeyPrefixType(self) -> definitions.KeyPrefixType:
99
102
  """Returns the KeyPrefixType.
@@ -116,7 +119,8 @@ class KeyPrefix(utils.FromDecoderMixin):
116
119
  if self.index_id >= 30:
117
120
  return definitions.KeyPrefixType.INDEX_DATA
118
121
  raise errors.ParserError(
119
- f'Unknown KeyPrefixType (index_id={self.index_id})')
122
+ f"Unknown KeyPrefixType (index_id={self.index_id})"
123
+ )
120
124
 
121
125
 
122
126
  @dataclass
@@ -128,9 +132,10 @@ class IDBKey(utils.FromDecoderMixin):
128
132
  type: the type of the IDBKey.
129
133
  value: the value of the IDBKey.
130
134
  """
135
+
131
136
  offset: int = field(compare=False)
132
137
  type: definitions.IDBKeyType
133
- value: Union[list, bytes, str, float, datetime, None]
138
+ value: Union[list[Any], bytes, str, float, datetime, None]
134
139
 
135
140
  _MAXIMUM_DEPTH = 2000
136
141
 
@@ -138,7 +143,7 @@ class IDBKey(utils.FromDecoderMixin):
138
143
  def FromDecoder(
139
144
  cls,
140
145
  decoder: utils.LevelDBDecoder,
141
- base_offset: int = 0 #pylint: disable=unused-argument
146
+ base_offset: int = 0, # pylint: disable=unused-argument
142
147
  ) -> IDBKey:
143
148
  """Decodes an IDBKey from the current position of a LevelDBDecoder.
144
149
 
@@ -155,10 +160,13 @@ class IDBKey(utils.FromDecoderMixin):
155
160
  RecursionError: if maximum depth encountered during parsing.
156
161
  """
157
162
 
158
- def RecursiveParse(depth: int) -> Tuple[
159
- int, definitions.IDBKeyType, Union[
160
- list, bytes, str, float, datetime, None
161
- ]]:
163
+ def RecursiveParse(
164
+ depth: int,
165
+ ) -> Tuple[
166
+ int,
167
+ definitions.IDBKeyType,
168
+ Union[list[Any], bytes, str, float, datetime, None],
169
+ ]:
162
170
  """Recursively parses IDBKeys.
163
171
 
164
172
  Args:
@@ -174,16 +182,17 @@ class IDBKey(utils.FromDecoderMixin):
174
182
  RecursionError: if maximum depth encountered during parsing.
175
183
  """
176
184
  if depth == cls._MAXIMUM_DEPTH:
177
- raise RecursionError('Maximum recursion depth encountered during parse')
185
+ raise RecursionError("Maximum recursion depth encountered during parse")
178
186
  offset, key_type_value = decoder.DecodeInt(1)
179
187
  key_type = definitions.IDBKeyType(key_type_value)
188
+ value: Any = None
180
189
 
181
190
  if key_type == definitions.IDBKeyType.NULL:
182
191
  value = None
183
192
  elif key_type == definitions.IDBKeyType.ARRAY:
184
193
  _, length = decoder.DecodeVarint()
185
194
  if length < 0:
186
- raise errors.ParserError('Invalid length encountered')
195
+ raise errors.ParserError("Invalid length encountered")
187
196
  value = []
188
197
  while length:
189
198
  entry = RecursiveParse(depth + 1)
@@ -195,13 +204,13 @@ class IDBKey(utils.FromDecoderMixin):
195
204
  _, value = decoder.DecodeStringWithLength()
196
205
  elif key_type == definitions.IDBKeyType.DATE:
197
206
  _, raw_value = decoder.DecodeDouble()
198
- value = datetime.utcfromtimestamp(raw_value/1000.0)
207
+ value = datetime.utcfromtimestamp(raw_value / 1000.0)
199
208
  elif key_type == definitions.IDBKeyType.NUMBER:
200
209
  _, value = decoder.DecodeDouble()
201
210
  elif key_type == definitions.IDBKeyType.MIN_KEY:
202
211
  value = None
203
212
  else:
204
- raise errors.ParserError('Invalid IndexedDbKeyType')
213
+ raise errors.ParserError("Invalid IndexedDbKeyType")
205
214
  return offset, key_type, value
206
215
 
207
216
  offset, key_type, value = RecursiveParse(0)
@@ -217,15 +226,14 @@ class IDBKeyPath(utils.FromDecoderMixin):
217
226
  type: the IDBKeyPath type.
218
227
  value: the IDBKeyPath value.
219
228
  """
229
+
220
230
  offset: int = field(compare=False)
221
231
  type: definitions.IDBKeyPathType
222
232
  value: Union[str, list[str], None]
223
233
 
224
234
  @classmethod
225
235
  def FromDecoder(
226
- cls,
227
- decoder: utils.LevelDBDecoder,
228
- base_offset: int = 0
236
+ cls, decoder: utils.LevelDBDecoder, base_offset: int = 0
229
237
  ) -> IDBKeyPath:
230
238
  """Decodes an IDBKeyPath from the current position of a LevelDBDecoder.
231
239
 
@@ -240,11 +248,13 @@ class IDBKeyPath(utils.FromDecoderMixin):
240
248
  ParserError: on insufficient bytes or invalid array length during
241
249
  parsing or unsupported key path type.
242
250
  """
243
- buffer = decoder.stream.getvalue() #pytype: disable=attribute-error
251
+ buffer = decoder.stream.getvalue() # type: ignore[attr-defined]
244
252
  if len(buffer) < 3:
245
- raise errors.ParserError('Insufficient bytes to parse.')
253
+ raise errors.ParserError("Insufficient bytes to parse.")
246
254
 
247
- if buffer[0:2] != b'\x00\x00':
255
+ value: str | list[str] | None = None
256
+
257
+ if buffer[0:2] != b"\x00\x00":
248
258
  offset, value = decoder.DecodeString()
249
259
  return IDBKeyPath(offset, definitions.IDBKeyPathType.STRING, value)
250
260
 
@@ -261,12 +271,12 @@ class IDBKeyPath(utils.FromDecoderMixin):
261
271
  value = []
262
272
  offset, count = decoder.DecodeVarint()
263
273
  if count < 0:
264
- raise errors.ParserError(f'Invalid array length {count}')
274
+ raise errors.ParserError(f"Invalid array length {count}")
265
275
  for _ in range(count):
266
276
  _, entry = decoder.DecodeStringWithLength()
267
277
  value.append(entry)
268
278
  else:
269
- raise errors.ParserError(f'Unsupported key_path_type {key_path_type}.')
279
+ raise errors.ParserError(f"Unsupported key_path_type {key_path_type}.")
270
280
  return IDBKeyPath(base_offset + offset, key_path_type, value)
271
281
 
272
282
 
@@ -279,15 +289,14 @@ class BlobJournalEntry(utils.FromDecoderMixin):
279
289
  database_id (int): the database ID.
280
290
  blob_number (int): the blob number.
281
291
  """
292
+
282
293
  offset: int = field(compare=False)
283
294
  database_id: int
284
295
  blob_number: int
285
296
 
286
297
  @classmethod
287
298
  def FromDecoder(
288
- cls,
289
- decoder: utils.LevelDBDecoder,
290
- base_offset: int = 0
299
+ cls, decoder: utils.LevelDBDecoder, base_offset: int = 0
291
300
  ) -> BlobJournalEntry:
292
301
  """Decodes a BlobJournalEntry from the current position of a LevelDBDecoder.
293
302
 
@@ -300,8 +309,11 @@ class BlobJournalEntry(utils.FromDecoderMixin):
300
309
  """
301
310
  offset, database_id = decoder.DecodeUint64Varint()
302
311
  _, blob_number = decoder.DecodeUint64Varint()
303
- return cls(offset=base_offset + offset, database_id=database_id,
304
- blob_number=blob_number)
312
+ return cls(
313
+ offset=base_offset + offset,
314
+ database_id=database_id,
315
+ blob_number=blob_number,
316
+ )
305
317
 
306
318
 
307
319
  @dataclass
@@ -312,14 +324,13 @@ class BlobJournal(utils.FromDecoderMixin):
312
324
  offset (int): the offset.
313
325
  entries (list[BlobJournalEntry]): the list of blob journal entries.
314
326
  """
327
+
315
328
  offset: int = field(compare=False)
316
329
  entries: list[BlobJournalEntry]
317
330
 
318
331
  @classmethod
319
332
  def FromDecoder(
320
- cls,
321
- decoder: utils.LevelDBDecoder,
322
- base_offset: int = 0
333
+ cls, decoder: utils.LevelDBDecoder, base_offset: int = 0
323
334
  ) -> BlobJournal:
324
335
  """Decodes a BlobJournal from the current position of a LevelDBDecoder.
325
336
 
@@ -360,6 +371,7 @@ class BaseIndexedDBKey:
360
371
  offset: the offset of the key (after the key_prefix).
361
372
  key_prefix: the key prefix.
362
373
  """
374
+
363
375
  offset: int
364
376
  key_prefix: KeyPrefix
365
377
 
@@ -374,7 +386,7 @@ class BaseIndexedDBKey:
374
386
  Raises:
375
387
  NotImplementedError.
376
388
  """
377
- raise NotImplementedError(f'{self.__class__.__name__}.decode_value')
389
+ raise NotImplementedError(f"{self.__class__.__name__}.decode_value")
378
390
 
379
391
  def ParseValue(self, value_data: bytes) -> Any:
380
392
  """Parses the value from raw bytes.
@@ -392,11 +404,11 @@ class BaseIndexedDBKey:
392
404
 
393
405
  @classmethod
394
406
  def FromDecoder(
395
- cls: T,
407
+ cls: Type[T],
396
408
  decoder: utils.LevelDBDecoder,
397
409
  key_prefix: KeyPrefix,
398
- base_offset: int = 0
399
- ) -> T: #pylint: disable=unused-variable
410
+ base_offset: int = 0,
411
+ ) -> T: # pylint: disable=unused-variable
400
412
  """Decodes the remaining key data from the current decoder position.
401
413
 
402
414
  Args:
@@ -410,7 +422,7 @@ class BaseIndexedDBKey:
410
422
  Raises:
411
423
  NotImplementedError.
412
424
  """
413
- raise NotImplementedError(f'{cls.__class__.__name__}.decode_key')
425
+ raise NotImplementedError(f"{cls.__class__.__name__}.decode_key")
414
426
 
415
427
  @classmethod
416
428
  def FromStream(cls: Type[T], stream: BinaryIO, base_offset: int = 0) -> T:
@@ -425,8 +437,9 @@ class BaseIndexedDBKey:
425
437
  """
426
438
  decoder = utils.LevelDBDecoder(stream)
427
439
  key_prefix = KeyPrefix.FromDecoder(decoder, base_offset=base_offset)
428
- return cls.FromDecoder(
429
- decoder=decoder, key_prefix=key_prefix, base_offset=base_offset)
440
+ return cls.FromDecoder( # type: ignore[no-any-return,attr-defined]
441
+ decoder=decoder, key_prefix=key_prefix, base_offset=base_offset
442
+ )
430
443
 
431
444
  @classmethod
432
445
  def FromBytes(cls: Type[T], raw_data: bytes, base_offset: int = 0) -> T:
@@ -440,7 +453,9 @@ class BaseIndexedDBKey:
440
453
  The decoded key.
441
454
  """
442
455
  stream = io.BytesIO(raw_data)
443
- return cls.FromStream(stream=stream, base_offset=base_offset)
456
+ return cls.FromStream( # type: ignore[no-any-return,attr-defined]
457
+ stream=stream, base_offset=base_offset
458
+ )
444
459
 
445
460
 
446
461
  @dataclass
@@ -456,12 +471,12 @@ class SchemaVersionKey(BaseIndexedDBKey):
456
471
  cls,
457
472
  decoder: utils.LevelDBDecoder,
458
473
  key_prefix: KeyPrefix,
459
- base_offset: int = 0
474
+ base_offset: int = 0,
460
475
  ) -> SchemaVersionKey:
461
476
  """Decodes the schema version key."""
462
477
  offset, key_type = decoder.DecodeUint8()
463
478
  if key_type != definitions.GlobalMetadataKeyType.SCHEMA_VERSION:
464
- raise errors.ParserError('Not a SchemaVersionKey')
479
+ raise errors.ParserError("Not a SchemaVersionKey")
465
480
  return cls(offset=base_offset + offset, key_prefix=key_prefix)
466
481
 
467
482
 
@@ -478,12 +493,12 @@ class MaxDatabaseIdKey(BaseIndexedDBKey):
478
493
  cls,
479
494
  decoder: utils.LevelDBDecoder,
480
495
  key_prefix: KeyPrefix,
481
- base_offset: int = 0
496
+ base_offset: int = 0,
482
497
  ) -> MaxDatabaseIdKey:
483
498
  """Decodes the maximum database key."""
484
499
  offset, key_type = decoder.DecodeUint8()
485
500
  if key_type != definitions.GlobalMetadataKeyType.MAX_DATABASE_ID:
486
- raise errors.ParserError('Not a MaxDatabaseIdKey')
501
+ raise errors.ParserError("Not a MaxDatabaseIdKey")
487
502
  return cls(offset=base_offset + offset, key_prefix=key_prefix)
488
503
 
489
504
 
@@ -500,12 +515,12 @@ class DataVersionKey(BaseIndexedDBKey):
500
515
  cls,
501
516
  decoder: utils.LevelDBDecoder,
502
517
  key_prefix: KeyPrefix,
503
- base_offset: int = 0
518
+ base_offset: int = 0,
504
519
  ) -> DataVersionKey:
505
520
  """Decodes the data version key."""
506
521
  offset, key_type = decoder.DecodeUint8()
507
522
  if key_type != definitions.GlobalMetadataKeyType.DATA_VERSION:
508
- raise errors.ParserError('Not a DataVersionKey')
523
+ raise errors.ParserError("Not a DataVersionKey")
509
524
  return cls(offset=base_offset + offset, key_prefix=key_prefix)
510
525
 
511
526
 
@@ -522,12 +537,12 @@ class RecoveryBlobJournalKey(BaseIndexedDBKey):
522
537
  cls,
523
538
  decoder: utils.LevelDBDecoder,
524
539
  key_prefix: KeyPrefix,
525
- base_offset: int = 0
540
+ base_offset: int = 0,
526
541
  ) -> RecoveryBlobJournalKey:
527
542
  """Decodes the recovery blob journal key."""
528
543
  offset, key_type = decoder.DecodeUint8()
529
544
  if key_type != definitions.GlobalMetadataKeyType.RECOVERY_BLOB_JOURNAL:
530
- raise errors.ParserError('Not a RecoveryBlobJournalKey')
545
+ raise errors.ParserError("Not a RecoveryBlobJournalKey")
531
546
  return cls(offset=base_offset + offset, key_prefix=key_prefix)
532
547
 
533
548
 
@@ -544,12 +559,12 @@ class ActiveBlobJournalKey(BaseIndexedDBKey):
544
559
  cls,
545
560
  decoder: utils.LevelDBDecoder,
546
561
  key_prefix: KeyPrefix,
547
- base_offset: int = 0
562
+ base_offset: int = 0,
548
563
  ) -> ActiveBlobJournalKey:
549
564
  """Decodes the active blob journal value."""
550
565
  offset, key_type = decoder.DecodeUint8()
551
566
  if key_type != definitions.GlobalMetadataKeyType.ACTIVE_BLOB_JOURNAL:
552
- raise errors.ParserError('Not a ActiveBlobJournalKey')
567
+ raise errors.ParserError("Not a ActiveBlobJournalKey")
553
568
  return cls(offset=base_offset + offset, key_prefix=key_prefix)
554
569
 
555
570
 
@@ -560,19 +575,19 @@ class EarliestSweepKey(BaseIndexedDBKey):
560
575
  def DecodeValue(self, decoder: utils.LevelDBDecoder) -> int:
561
576
  """Decodes the earliest sweep value."""
562
577
  _, data = decoder.ReadBytes()
563
- return int.from_bytes(data, byteorder='little', signed=False)
578
+ return int.from_bytes(data, byteorder="little", signed=False)
564
579
 
565
580
  @classmethod
566
581
  def FromDecoder(
567
582
  cls,
568
583
  decoder: utils.LevelDBDecoder,
569
584
  key_prefix: KeyPrefix,
570
- base_offset: int = 0
585
+ base_offset: int = 0,
571
586
  ) -> EarliestSweepKey:
572
587
  """Decodes the earliest sweep value."""
573
588
  offset, key_type = decoder.DecodeUint8()
574
589
  if key_type != definitions.GlobalMetadataKeyType.EARLIEST_SWEEP:
575
- raise errors.ParserError('Not a EarliestSweepKey')
590
+ raise errors.ParserError("Not a EarliestSweepKey")
576
591
  return cls(offset=base_offset + offset, key_prefix=key_prefix)
577
592
 
578
593
 
@@ -583,19 +598,19 @@ class EarliestCompactionTimeKey(BaseIndexedDBKey):
583
598
  def DecodeValue(self, decoder: utils.LevelDBDecoder) -> int:
584
599
  """Decodes the earliest compaction time value."""
585
600
  _, data = decoder.ReadBytes()
586
- return int.from_bytes(data, byteorder='little', signed=False)
601
+ return int.from_bytes(data, byteorder="little", signed=False)
587
602
 
588
603
  @classmethod
589
604
  def FromDecoder(
590
605
  cls,
591
606
  decoder: utils.LevelDBDecoder,
592
607
  key_prefix: KeyPrefix,
593
- base_offset: int = 0
608
+ base_offset: int = 0,
594
609
  ) -> EarliestCompactionTimeKey:
595
610
  """Decodes the earliest compaction time key."""
596
611
  offset, key_type = decoder.DecodeUint8()
597
612
  if key_type != definitions.GlobalMetadataKeyType.EARLIEST_COMPACTION_TIME:
598
- raise errors.ParserError('Not a EarliestCompactionTimeKey')
613
+ raise errors.ParserError("Not a EarliestCompactionTimeKey")
599
614
  return cls(offset=base_offset + offset, key_prefix=key_prefix)
600
615
 
601
616
 
@@ -605,7 +620,7 @@ class ScopesPrefixKey(BaseIndexedDBKey):
605
620
 
606
621
  def DecodeValue(self, decoder: utils.LevelDBDecoder) -> Optional[bytes]:
607
622
  """Decodes the scopes prefix value."""
608
- if decoder.NumRemainingBytes:
623
+ if decoder.NumRemainingBytes():
609
624
  return decoder.ReadBytes()[1]
610
625
  return None
611
626
 
@@ -614,12 +629,12 @@ class ScopesPrefixKey(BaseIndexedDBKey):
614
629
  cls,
615
630
  decoder: utils.LevelDBDecoder,
616
631
  key_prefix: KeyPrefix,
617
- base_offset: int = 0
632
+ base_offset: int = 0,
618
633
  ) -> ScopesPrefixKey:
619
634
  """Decodes the scopes prefix key."""
620
635
  offset, key_type = decoder.DecodeUint8()
621
636
  if key_type != definitions.GlobalMetadataKeyType.SCOPES_PREFIX:
622
- raise errors.ParserError('Not a ScopesPrefixKey')
637
+ raise errors.ParserError("Not a ScopesPrefixKey")
623
638
  return cls(offset=base_offset + offset, key_prefix=key_prefix)
624
639
 
625
640
 
@@ -630,27 +645,30 @@ class DatabaseFreeListKey(BaseIndexedDBKey):
630
645
  Attributes:
631
646
  database_id: the database ID.
632
647
  """
648
+
633
649
  database_id: int
634
650
 
635
- def DecodeValue(self, decoder: utils.LevelDBDecoder):
651
+ def DecodeValue(self, decoder: utils.LevelDBDecoder) -> None:
636
652
  """Decodes the database free list value."""
637
- raise NotImplementedError('DatabaseFreeListKey.decode_value')
653
+ raise NotImplementedError("DatabaseFreeListKey.decode_value")
638
654
 
639
655
  @classmethod
640
656
  def FromDecoder(
641
657
  cls,
642
658
  decoder: utils.LevelDBDecoder,
643
659
  key_prefix: KeyPrefix,
644
- base_offset: int = 0
660
+ base_offset: int = 0,
645
661
  ) -> DatabaseFreeListKey:
646
662
  """Decodes the database free list key."""
647
663
  offset, key_type = decoder.DecodeUint8()
648
664
  if key_type != definitions.GlobalMetadataKeyType.DATABASE_FREE_LIST:
649
- raise errors.ParserError('Not a DatabaseFreeListKey')
665
+ raise errors.ParserError("Not a DatabaseFreeListKey")
650
666
  _, database_id = decoder.DecodeVarint()
651
667
  return cls(
652
- offset=base_offset + offset, key_prefix=key_prefix,
653
- database_id=database_id)
668
+ offset=base_offset + offset,
669
+ key_prefix=key_prefix,
670
+ database_id=database_id,
671
+ )
654
672
 
655
673
 
656
674
  @dataclass
@@ -661,6 +679,7 @@ class DatabaseNameKey(BaseIndexedDBKey):
661
679
  origin: the origin of the database.
662
680
  database_name: the database name.
663
681
  """
682
+
664
683
  origin: str
665
684
  database_name: str
666
685
 
@@ -676,45 +695,40 @@ class DatabaseNameKey(BaseIndexedDBKey):
676
695
  cls,
677
696
  decoder: utils.LevelDBDecoder,
678
697
  key_prefix: KeyPrefix,
679
- base_offset: int = 0
698
+ base_offset: int = 0,
680
699
  ) -> DatabaseNameKey:
681
700
  """Decodes the database name key."""
682
701
  offset, key_type = decoder.DecodeUint8()
683
702
  if key_type != definitions.GlobalMetadataKeyType.DATABASE_NAME:
684
- raise errors.ParserError('Not a DatabaseNameKey')
703
+ raise errors.ParserError("Not a DatabaseNameKey")
685
704
  _, origin = decoder.DecodeStringWithLength()
686
705
  _, database_name = decoder.DecodeStringWithLength()
687
706
  return cls(
688
- offset=base_offset + offset, key_prefix=key_prefix, origin=origin,
689
- database_name=database_name)
707
+ offset=base_offset + offset,
708
+ key_prefix=key_prefix,
709
+ origin=origin,
710
+ database_name=database_name,
711
+ )
690
712
 
691
713
 
692
714
  @dataclass
693
715
  class GlobalMetaDataKey(BaseIndexedDBKey):
694
716
  """A GlobalMetaDataKey parser."""
695
717
 
718
+ # pylint: disable=line-too-long
696
719
  METADATA_TYPE_TO_CLASS = {
697
- definitions.GlobalMetadataKeyType
698
- .ACTIVE_BLOB_JOURNAL: ActiveBlobJournalKey,
699
- definitions.GlobalMetadataKeyType
700
- .DATA_VERSION: DataVersionKey,
701
- definitions.GlobalMetadataKeyType
702
- .DATABASE_FREE_LIST: DatabaseFreeListKey,
703
- definitions.GlobalMetadataKeyType
704
- .DATABASE_NAME: DatabaseNameKey,
705
- definitions.GlobalMetadataKeyType
706
- .EARLIEST_COMPACTION_TIME: EarliestCompactionTimeKey,
707
- definitions.GlobalMetadataKeyType
708
- .EARLIEST_SWEEP: EarliestSweepKey,
709
- definitions.GlobalMetadataKeyType
710
- .MAX_DATABASE_ID: MaxDatabaseIdKey,
711
- definitions.GlobalMetadataKeyType
712
- .RECOVERY_BLOB_JOURNAL: RecoveryBlobJournalKey,
713
- definitions.GlobalMetadataKeyType
714
- .SCHEMA_VERSION: SchemaVersionKey,
715
- definitions.GlobalMetadataKeyType
716
- .SCOPES_PREFIX: ScopesPrefixKey,
720
+ definitions.GlobalMetadataKeyType.ACTIVE_BLOB_JOURNAL: ActiveBlobJournalKey,
721
+ definitions.GlobalMetadataKeyType.DATA_VERSION: DataVersionKey,
722
+ definitions.GlobalMetadataKeyType.DATABASE_FREE_LIST: DatabaseFreeListKey,
723
+ definitions.GlobalMetadataKeyType.DATABASE_NAME: DatabaseNameKey,
724
+ definitions.GlobalMetadataKeyType.EARLIEST_COMPACTION_TIME: EarliestCompactionTimeKey,
725
+ definitions.GlobalMetadataKeyType.EARLIEST_SWEEP: EarliestSweepKey,
726
+ definitions.GlobalMetadataKeyType.MAX_DATABASE_ID: MaxDatabaseIdKey,
727
+ definitions.GlobalMetadataKeyType.RECOVERY_BLOB_JOURNAL: RecoveryBlobJournalKey,
728
+ definitions.GlobalMetadataKeyType.SCHEMA_VERSION: SchemaVersionKey,
729
+ definitions.GlobalMetadataKeyType.SCOPES_PREFIX: ScopesPrefixKey,
717
730
  }
731
+ # pylint: enable=line-too-long
718
732
 
719
733
  def DecodeValue(self, decoder: utils.LevelDBDecoder) -> Any:
720
734
  """Decodes the value from the current position of the LevelDBDecoder.
@@ -728,17 +742,19 @@ class GlobalMetaDataKey(BaseIndexedDBKey):
728
742
  cls,
729
743
  decoder: utils.LevelDBDecoder,
730
744
  key_prefix: KeyPrefix,
731
- base_offset: int = 0
732
- ) -> Union[ActiveBlobJournalKey,
733
- DataVersionKey,
734
- DatabaseFreeListKey,
735
- DatabaseNameKey,
736
- EarliestSweepKey,
737
- EarliestCompactionTimeKey,
738
- MaxDatabaseIdKey,
739
- RecoveryBlobJournalKey,
740
- SchemaVersionKey,
741
- ScopesPrefixKey]:
745
+ base_offset: int = 0,
746
+ ) -> Union[
747
+ ActiveBlobJournalKey,
748
+ DataVersionKey,
749
+ DatabaseFreeListKey,
750
+ DatabaseNameKey,
751
+ EarliestSweepKey,
752
+ EarliestCompactionTimeKey,
753
+ MaxDatabaseIdKey,
754
+ RecoveryBlobJournalKey,
755
+ SchemaVersionKey,
756
+ ScopesPrefixKey,
757
+ ]:
742
758
  """Decodes the global metadata key.
743
759
 
744
760
  Raises:
@@ -749,9 +765,10 @@ class GlobalMetaDataKey(BaseIndexedDBKey):
749
765
 
750
766
  key_class = cls.METADATA_TYPE_TO_CLASS.get(metadata_type)
751
767
  if not key_class:
752
- raise errors.ParserError('Unknown metadata key type')
753
- return key_class.FromDecoder(
754
- decoder, key_prefix, base_offset)
768
+ raise errors.ParserError("Unknown metadata key type")
769
+ return key_class.FromDecoder( # type: ignore[attr-defined,no-any-return]
770
+ decoder, key_prefix, base_offset
771
+ )
755
772
 
756
773
 
757
774
  @dataclass
@@ -761,27 +778,30 @@ class ObjectStoreFreeListKey(BaseIndexedDBKey):
761
778
  Attributes:
762
779
  object_store_id: the ID of the object store containing the free list.
763
780
  """
781
+
764
782
  object_store_id: int
765
783
 
766
- def DecodeValue(self, decoder: utils.LevelDBDecoder):
784
+ def DecodeValue(self, decoder: utils.LevelDBDecoder) -> None:
767
785
  """Decodes the object store free list value."""
768
- raise NotImplementedError('ObjectStoreFreeListKey.decode_value')
786
+ raise NotImplementedError("ObjectStoreFreeListKey.decode_value")
769
787
 
770
788
  @classmethod
771
789
  def FromDecoder(
772
790
  cls,
773
791
  decoder: utils.LevelDBDecoder,
774
792
  key_prefix: KeyPrefix,
775
- base_offset: int = 0
793
+ base_offset: int = 0,
776
794
  ) -> ObjectStoreFreeListKey:
777
795
  """Decodes the object store free list key."""
778
796
  offset, key_type = decoder.DecodeUint8()
779
797
  if key_type != definitions.DatabaseMetaDataKeyType.OBJECT_STORE_FREE_LIST:
780
- raise errors.ParserError('Not am ObjectStoreFreeListKey')
798
+ raise errors.ParserError("Not am ObjectStoreFreeListKey")
781
799
  _, object_store_id = decoder.DecodeVarint()
782
800
  return cls(
783
- offset=base_offset + offset, key_prefix=key_prefix,
784
- object_store_id=object_store_id)
801
+ offset=base_offset + offset,
802
+ key_prefix=key_prefix,
803
+ object_store_id=object_store_id,
804
+ )
785
805
 
786
806
 
787
807
  @dataclass
@@ -791,27 +811,30 @@ class IndexFreeListKey(BaseIndexedDBKey):
791
811
  Attributes:
792
812
  object_store_id: the ID of the object store containing the free list.
793
813
  """
814
+
794
815
  object_store_id: int
795
816
 
796
- def DecodeValue(self, decoder: utils.LevelDBDecoder):
817
+ def DecodeValue(self, decoder: utils.LevelDBDecoder) -> None:
797
818
  """Decodes the index free list value."""
798
- raise NotImplementedError('IndexFreeListKey.decode_value')
819
+ raise NotImplementedError("IndexFreeListKey.decode_value")
799
820
 
800
821
  @classmethod
801
822
  def FromDecoder(
802
823
  cls,
803
824
  decoder: utils.LevelDBDecoder,
804
825
  key_prefix: KeyPrefix,
805
- base_offset: int = 0
806
- ) -> IndexFreeListKey:
826
+ base_offset: int = 0,
827
+ ) -> IndexFreeListKey:
807
828
  """Decodes the index free list key."""
808
829
  offset, key_type = decoder.DecodeUint8()
809
830
  if key_type != definitions.DatabaseMetaDataKeyType.INDEX_FREE_LIST:
810
- raise errors.ParserError('Not am IndexFreeListKey')
831
+ raise errors.ParserError("Not am IndexFreeListKey")
811
832
  _, object_store_id = decoder.DecodeVarint()
812
833
  return cls(
813
- offset=base_offset + offset, key_prefix=key_prefix,
814
- object_store_id=object_store_id)
834
+ offset=base_offset + offset,
835
+ key_prefix=key_prefix,
836
+ object_store_id=object_store_id,
837
+ )
815
838
 
816
839
 
817
840
  @dataclass
@@ -821,6 +844,7 @@ class ObjectStoreNamesKey(BaseIndexedDBKey):
821
844
  Attributes:
822
845
  object_store_name: the name of the object store.
823
846
  """
847
+
824
848
  object_store_name: str
825
849
 
826
850
  def DecodeValue(self, decoder: utils.LevelDBDecoder) -> int:
@@ -829,17 +853,21 @@ class ObjectStoreNamesKey(BaseIndexedDBKey):
829
853
 
830
854
  @classmethod
831
855
  def FromDecoder(
832
- cls, decoder: utils.LevelDBDecoder,
856
+ cls,
857
+ decoder: utils.LevelDBDecoder,
833
858
  key_prefix: KeyPrefix,
834
- base_offset: int = 0
859
+ base_offset: int = 0,
835
860
  ) -> ObjectStoreNamesKey:
836
861
  """Decodes the object store names key."""
837
862
  offset, key_type = decoder.DecodeUint8()
838
863
  if key_type != definitions.DatabaseMetaDataKeyType.OBJECT_STORE_NAMES:
839
- raise errors.ParserError('Not am ObjectStoreNamesKey')
864
+ raise errors.ParserError("Not am ObjectStoreNamesKey")
840
865
  _, object_store_name = decoder.DecodeStringWithLength()
841
- return cls(key_prefix=key_prefix, offset=base_offset + offset,
842
- object_store_name=object_store_name)
866
+ return cls(
867
+ key_prefix=key_prefix,
868
+ offset=base_offset + offset,
869
+ object_store_name=object_store_name,
870
+ )
843
871
 
844
872
 
845
873
  @dataclass
@@ -849,6 +877,7 @@ class IndexNamesKey(BaseIndexedDBKey):
849
877
  Attributes:
850
878
  index_name: the name of the index.
851
879
  """
880
+
852
881
  index_name: str
853
882
 
854
883
  def DecodeValue(self, decoder: utils.LevelDBDecoder) -> int:
@@ -860,15 +889,18 @@ class IndexNamesKey(BaseIndexedDBKey):
860
889
  cls,
861
890
  decoder: utils.LevelDBDecoder,
862
891
  key_prefix: KeyPrefix,
863
- base_offset: int = 0
892
+ base_offset: int = 0,
864
893
  ) -> IndexNamesKey:
865
894
  """Decodes the index names key."""
866
895
  offset, key_type = decoder.DecodeUint8()
867
896
  if key_type != definitions.DatabaseMetaDataKeyType.INDEX_NAMES:
868
- raise errors.ParserError('Not am IndexNamesKey')
897
+ raise errors.ParserError("Not am IndexNamesKey")
869
898
  _, index_name = decoder.DecodeStringWithLength()
870
- return cls(key_prefix=key_prefix, offset=base_offset + offset,
871
- index_name=index_name)
899
+ return cls(
900
+ key_prefix=key_prefix,
901
+ offset=base_offset + offset,
902
+ index_name=index_name,
903
+ )
872
904
 
873
905
 
874
906
  @dataclass
@@ -878,39 +910,45 @@ class DatabaseMetaDataKey(BaseIndexedDBKey):
878
910
  Attributes:
879
911
  metadata_type: the type of metadata that the key value contains.
880
912
  """
913
+
881
914
  metadata_type: definitions.DatabaseMetaDataKeyType
882
915
 
883
- def DecodeValue(
884
- self, decoder: utils.LevelDBDecoder) -> Union[str, int]:
916
+ def DecodeValue(self, decoder: utils.LevelDBDecoder) -> Union[str, int]:
885
917
  """Decodes the database metadata value."""
886
- if (self.metadata_type ==
887
- definitions.DatabaseMetaDataKeyType.ORIGIN_NAME):
918
+ if self.metadata_type == definitions.DatabaseMetaDataKeyType.ORIGIN_NAME:
888
919
  return decoder.DecodeString()[1]
889
- if (self.metadata_type ==
890
- definitions.DatabaseMetaDataKeyType.DATABASE_NAME):
920
+ if self.metadata_type == definitions.DatabaseMetaDataKeyType.DATABASE_NAME:
891
921
  return decoder.DecodeString()[1]
892
- if (self.metadata_type ==
893
- definitions.DatabaseMetaDataKeyType.IDB_STRING_VERSION_DATA):
922
+ if (
923
+ self.metadata_type
924
+ == definitions.DatabaseMetaDataKeyType.IDB_STRING_VERSION_DATA
925
+ ):
894
926
  return decoder.DecodeString()[1]
895
- if (self.metadata_type ==
896
- definitions.DatabaseMetaDataKeyType.MAX_ALLOCATED_OBJECT_STORE_ID):
927
+ if (
928
+ self.metadata_type
929
+ == definitions.DatabaseMetaDataKeyType.MAX_ALLOCATED_OBJECT_STORE_ID
930
+ ):
897
931
  return decoder.DecodeInt()[1]
898
- if (self.metadata_type ==
899
- definitions.DatabaseMetaDataKeyType.IDB_INTEGER_VERSION):
932
+ if (
933
+ self.metadata_type
934
+ == definitions.DatabaseMetaDataKeyType.IDB_INTEGER_VERSION
935
+ ):
900
936
  return decoder.DecodeVarint()[1]
901
- if (self.metadata_type ==
902
- definitions.DatabaseMetaDataKeyType
903
- .BLOB_NUMBER_GENERATOR_CURRENT_NUMBER):
937
+ if (
938
+ self.metadata_type
939
+ == definitions.DatabaseMetaDataKeyType.BLOB_NUMBER_GENERATOR_CURRENT_NUMBER # pylint: disable=line-too-long
940
+ ):
904
941
  return decoder.DecodeVarint()[1]
905
942
  raise errors.ParserError(
906
- f'Unknown database metadata type {self.metadata_type}')
943
+ f"Unknown database metadata type {self.metadata_type}"
944
+ )
907
945
 
908
946
  @classmethod
909
947
  def FromDecoder(
910
948
  cls,
911
949
  decoder: utils.LevelDBDecoder,
912
950
  key_prefix: KeyPrefix,
913
- base_offset: int = 0
951
+ base_offset: int = 0,
914
952
  ) -> Union[
915
953
  DatabaseMetaDataKey,
916
954
  IndexFreeListKey,
@@ -918,7 +956,8 @@ class DatabaseMetaDataKey(BaseIndexedDBKey):
918
956
  IndexNamesKey,
919
957
  ObjectStoreFreeListKey,
920
958
  ObjectStoreMetaDataKey,
921
- ObjectStoreNamesKey]:
959
+ ObjectStoreNamesKey,
960
+ ]:
922
961
  """Decodes the database metadata key."""
923
962
  offset, metadata_value = decoder.PeekBytes(1)
924
963
  metadata_type = definitions.DatabaseMetaDataKeyType(metadata_value[0])
@@ -929,32 +968,36 @@ class DatabaseMetaDataKey(BaseIndexedDBKey):
929
968
  definitions.DatabaseMetaDataKeyType.IDB_STRING_VERSION_DATA,
930
969
  definitions.DatabaseMetaDataKeyType.MAX_ALLOCATED_OBJECT_STORE_ID,
931
970
  definitions.DatabaseMetaDataKeyType.IDB_INTEGER_VERSION,
932
- definitions.DatabaseMetaDataKeyType
933
- .BLOB_NUMBER_GENERATOR_CURRENT_NUMBER):
934
- return cls(key_prefix=key_prefix, offset=base_offset + offset,
935
- metadata_type=metadata_type)
971
+ definitions.DatabaseMetaDataKeyType.BLOB_NUMBER_GENERATOR_CURRENT_NUMBER, # pylint: disable=line-too-long
972
+ ):
973
+ return cls(
974
+ key_prefix=key_prefix,
975
+ offset=base_offset + offset,
976
+ metadata_type=metadata_type,
977
+ )
936
978
  if metadata_type == definitions.DatabaseMetaDataKeyType.INDEX_META_DATA:
937
- return IndexMetaDataKey.FromDecoder(
938
- decoder, key_prefix, base_offset)
939
- if (metadata_type ==
940
- definitions.DatabaseMetaDataKeyType.OBJECT_STORE_META_DATA):
979
+ return IndexMetaDataKey.FromDecoder(decoder, key_prefix, base_offset)
980
+ if (
981
+ metadata_type
982
+ == definitions.DatabaseMetaDataKeyType.OBJECT_STORE_META_DATA
983
+ ):
941
984
  return ObjectStoreMetaDataKey.FromDecoder(
942
- decoder, key_prefix, base_offset)
943
- if (metadata_type ==
944
- definitions.DatabaseMetaDataKeyType.OBJECT_STORE_FREE_LIST):
985
+ decoder, key_prefix, base_offset
986
+ )
987
+ if (
988
+ metadata_type
989
+ == definitions.DatabaseMetaDataKeyType.OBJECT_STORE_FREE_LIST
990
+ ):
945
991
  return ObjectStoreFreeListKey.FromDecoder(
946
- decoder, key_prefix, base_offset)
992
+ decoder, key_prefix, base_offset
993
+ )
947
994
  if metadata_type == definitions.DatabaseMetaDataKeyType.INDEX_FREE_LIST:
948
- return IndexFreeListKey.FromDecoder(
949
- decoder, key_prefix, base_offset)
950
- if (metadata_type ==
951
- definitions.DatabaseMetaDataKeyType.OBJECT_STORE_NAMES):
952
- return ObjectStoreNamesKey.FromDecoder(
953
- decoder, key_prefix, base_offset)
995
+ return IndexFreeListKey.FromDecoder(decoder, key_prefix, base_offset)
996
+ if metadata_type == definitions.DatabaseMetaDataKeyType.OBJECT_STORE_NAMES:
997
+ return ObjectStoreNamesKey.FromDecoder(decoder, key_prefix, base_offset)
954
998
  if metadata_type == definitions.DatabaseMetaDataKeyType.INDEX_NAMES:
955
- return IndexNamesKey.FromDecoder(
956
- decoder, key_prefix, base_offset)
957
- raise errors.ParserError(f'unknown database metadata type {metadata_type}.')
999
+ return IndexNamesKey.FromDecoder(decoder, key_prefix, base_offset)
1000
+ raise errors.ParserError(f"unknown database metadata type {metadata_type}.")
958
1001
 
959
1002
 
960
1003
  @dataclass
@@ -965,58 +1008,78 @@ class ObjectStoreMetaDataKey(BaseIndexedDBKey):
965
1008
  object_store_id: the ID of the object store.
966
1009
  metadata_type: the object store metadata type.
967
1010
  """
1011
+
968
1012
  object_store_id: int
969
1013
  metadata_type: definitions.ObjectStoreMetaDataKeyType
970
1014
 
971
1015
  def DecodeValue(
972
- self,
973
- decoder: utils.LevelDBDecoder
1016
+ self, decoder: utils.LevelDBDecoder
974
1017
  ) -> Union[IDBKeyPath, str, bool, int]:
975
1018
  """Decodes the object store metadata value."""
976
- if (self.metadata_type ==
977
- definitions.ObjectStoreMetaDataKeyType.OBJECT_STORE_NAME):
1019
+ if (
1020
+ self.metadata_type
1021
+ == definitions.ObjectStoreMetaDataKeyType.OBJECT_STORE_NAME
1022
+ ):
978
1023
  return decoder.DecodeString()[1]
979
1024
  if self.metadata_type == definitions.ObjectStoreMetaDataKeyType.KEY_PATH:
980
1025
  return IDBKeyPath.FromDecoder(decoder)
981
- if (self.metadata_type ==
982
- definitions.ObjectStoreMetaDataKeyType.AUTO_INCREMENT_FLAG):
1026
+ if (
1027
+ self.metadata_type
1028
+ == definitions.ObjectStoreMetaDataKeyType.AUTO_INCREMENT_FLAG
1029
+ ):
983
1030
  return decoder.DecodeBool()[1]
984
- if (self.metadata_type ==
985
- definitions.ObjectStoreMetaDataKeyType.IS_EVICTABLE):
1031
+ if (
1032
+ self.metadata_type
1033
+ == definitions.ObjectStoreMetaDataKeyType.IS_EVICTABLE
1034
+ ):
986
1035
  return decoder.DecodeBool()[1]
987
- if (self.metadata_type ==
988
- definitions.ObjectStoreMetaDataKeyType.LAST_VERSION_NUMBER):
1036
+ if (
1037
+ self.metadata_type
1038
+ == definitions.ObjectStoreMetaDataKeyType.LAST_VERSION_NUMBER
1039
+ ):
989
1040
  return decoder.DecodeInt(signed=False)[1]
990
- if (self.metadata_type ==
991
- definitions.ObjectStoreMetaDataKeyType.MAXIMUM_ALLOCATED_INDEX_ID):
1041
+ if (
1042
+ self.metadata_type
1043
+ == definitions.ObjectStoreMetaDataKeyType.MAXIMUM_ALLOCATED_INDEX_ID
1044
+ ):
992
1045
  return decoder.DecodeInt()[1]
993
- if (self.metadata_type ==
994
- definitions.ObjectStoreMetaDataKeyType.HAS_KEY_PATH):
1046
+ if (
1047
+ self.metadata_type
1048
+ == definitions.ObjectStoreMetaDataKeyType.HAS_KEY_PATH
1049
+ ):
995
1050
  return decoder.DecodeBool()[1]
996
- if (self.metadata_type ==
997
- definitions.ObjectStoreMetaDataKeyType.KEY_GENERATOR_CURRENT_NUMBER):
1051
+ if (
1052
+ self.metadata_type
1053
+ == definitions.ObjectStoreMetaDataKeyType.KEY_GENERATOR_CURRENT_NUMBER
1054
+ ):
998
1055
  return decoder.DecodeInt()[1]
999
- raise errors.ParserError(f'Unknown metadata type {self.metadata_type}')
1056
+ raise errors.ParserError(f"Unknown metadata type {self.metadata_type}")
1000
1057
 
1001
1058
  @classmethod
1002
1059
  def FromDecoder(
1003
1060
  cls,
1004
1061
  decoder: utils.LevelDBDecoder,
1005
1062
  key_prefix: KeyPrefix,
1006
- base_offset: int = 0
1063
+ base_offset: int = 0,
1007
1064
  ) -> ObjectStoreMetaDataKey:
1008
1065
  """Decodes the object store metadata key."""
1009
1066
  offset, metadata_value = decoder.DecodeUint8()
1010
- if (metadata_value !=
1011
- definitions.DatabaseMetaDataKeyType.OBJECT_STORE_META_DATA):
1012
- raise errors.ParserError('Not a ObjectStoreMetaDataKey')
1067
+ if (
1068
+ metadata_value
1069
+ != definitions.DatabaseMetaDataKeyType.OBJECT_STORE_META_DATA
1070
+ ):
1071
+ raise errors.ParserError("Not a ObjectStoreMetaDataKey")
1013
1072
 
1014
1073
  _, object_store_id = decoder.DecodeVarint()
1015
1074
  _, metadata_value = decoder.DecodeUint8()
1016
1075
  metadata_type = definitions.ObjectStoreMetaDataKeyType(metadata_value)
1017
1076
  return cls(
1018
- offset=base_offset + offset, key_prefix=key_prefix,
1019
- object_store_id=object_store_id, metadata_type=metadata_type)
1077
+ offset=base_offset + offset,
1078
+ key_prefix=key_prefix,
1079
+ object_store_id=object_store_id,
1080
+ metadata_type=metadata_type,
1081
+ )
1082
+
1020
1083
 
1021
1084
  @dataclass
1022
1085
  class ObjectStoreDataValue:
@@ -1024,13 +1087,12 @@ class ObjectStoreDataValue:
1024
1087
 
1025
1088
  Attributes:
1026
1089
  version: the version prefix.
1027
- is_wrapped: True if the value was wrapped.
1028
1090
  blob_size: the blob size, only valid if wrapped.
1029
1091
  blob_offset: the blob offset, only valid if wrapped.
1030
1092
  value: the blink serialized value, only valid if not wrapped.
1031
1093
  """
1094
+
1032
1095
  version: int
1033
- is_wrapped: bool
1034
1096
  blob_size: Optional[int]
1035
1097
  blob_offset: Optional[int]
1036
1098
  value: Any
@@ -1043,68 +1105,59 @@ class ObjectStoreDataKey(BaseIndexedDBKey):
1043
1105
  Attributes:
1044
1106
  encoded_user_key: the encoded user key.
1045
1107
  """
1108
+
1046
1109
  encoded_user_key: IDBKey
1047
1110
 
1048
- def DecodeValue(
1049
- self,
1050
- decoder: utils.LevelDBDecoder
1051
- ) -> ObjectStoreDataValue:
1111
+ def DecodeValue(self, decoder: utils.LevelDBDecoder) -> ObjectStoreDataValue:
1052
1112
  """Decodes the object store data value."""
1053
1113
  _, version = decoder.DecodeVarint()
1054
1114
 
1055
1115
  _, wrapped_header_bytes = decoder.PeekBytes(3)
1056
1116
  if len(wrapped_header_bytes) != 3:
1057
- raise errors.DecoderError('Insufficient bytes')
1117
+ raise errors.DecoderError("Insufficient bytes")
1058
1118
 
1059
- if (wrapped_header_bytes[0] ==
1060
- definitions.BlinkSerializationTag.VERSION and
1061
- wrapped_header_bytes[1] ==
1062
- definitions.REQUIRES_PROCESSING_SSV_PSEUDO_VERSION and
1063
- wrapped_header_bytes[2] == definitions.REPLACE_WITH_BLOB):
1119
+ if (
1120
+ wrapped_header_bytes[0] == definitions.BlinkSerializationTag.VERSION
1121
+ and wrapped_header_bytes[1]
1122
+ == definitions.REQUIRES_PROCESSING_SSV_PSEUDO_VERSION
1123
+ and wrapped_header_bytes[2] == definitions.REPLACE_WITH_BLOB
1124
+ ):
1064
1125
  _ = decoder.ReadBytes(3)
1065
1126
  _, blob_size = decoder.DecodeVarint()
1066
1127
  _, blob_offset = decoder.DecodeVarint()
1067
1128
  return ObjectStoreDataValue(
1068
1129
  version=version,
1069
- is_wrapped=True,
1070
1130
  blob_size=blob_size,
1071
1131
  blob_offset=blob_offset,
1072
- value=None)
1132
+ value=None,
1133
+ )
1134
+
1073
1135
  _, blink_bytes = decoder.ReadBytes()
1074
- is_wrapped = False
1075
- if (
1076
- wrapped_header_bytes[0] ==
1077
- definitions.BlinkSerializationTag.VERSION and
1078
- wrapped_header_bytes[1] ==
1079
- definitions.REQUIRES_PROCESSING_SSV_PSEUDO_VERSION and
1080
- wrapped_header_bytes[2] == definitions.COMPRESSED_WITH_SNAPPY):
1081
- is_wrapped = True
1082
- # ignore the wrapped header bytes when decompressing
1083
- blink_bytes = snappy.decompress(blink_bytes[3:])
1084
1136
  blink_value = blink.V8ScriptValueDecoder.FromBytes(blink_bytes)
1085
1137
  return ObjectStoreDataValue(
1086
- version=version,
1087
- is_wrapped=is_wrapped,
1088
- blob_size=None,
1089
- blob_offset=None,
1090
- value=blink_value)
1138
+ version=version, blob_size=None, blob_offset=None, value=blink_value
1139
+ )
1091
1140
 
1092
1141
  @classmethod
1093
1142
  def FromDecoder(
1094
1143
  cls,
1095
1144
  decoder: utils.LevelDBDecoder,
1096
1145
  key_prefix: KeyPrefix,
1097
- base_offset: int = 0
1146
+ base_offset: int = 0,
1098
1147
  ) -> ObjectStoreDataKey:
1099
1148
  """Decodes the object store data key."""
1100
- if (key_prefix.GetKeyPrefixType() !=
1101
- definitions.KeyPrefixType.OBJECT_STORE_DATA):
1102
- raise errors.ParserError('Invalid KeyPrefix for ObjectStoreDataKey')
1149
+ if (
1150
+ key_prefix.GetKeyPrefixType()
1151
+ != definitions.KeyPrefixType.OBJECT_STORE_DATA
1152
+ ):
1153
+ raise errors.ParserError("Invalid KeyPrefix for ObjectStoreDataKey")
1103
1154
  offset = decoder.stream.tell()
1104
1155
  encoded_user_key = IDBKey.FromDecoder(decoder, offset)
1105
1156
  return cls(
1106
1157
  offset=base_offset + offset,
1107
- key_prefix=key_prefix, encoded_user_key=encoded_user_key)
1158
+ key_prefix=key_prefix,
1159
+ encoded_user_key=encoded_user_key,
1160
+ )
1108
1161
 
1109
1162
 
1110
1163
  @dataclass
@@ -1114,26 +1167,29 @@ class ExistsEntryKey(BaseIndexedDBKey):
1114
1167
  Attributes:
1115
1168
  encoded_user_key: the encoded user key.
1116
1169
  """
1170
+
1117
1171
  encoded_user_key: IDBKey
1118
1172
 
1119
1173
  def DecodeValue(self, decoder: utils.LevelDBDecoder) -> int:
1120
1174
  """Decodes the exists entry value."""
1121
1175
  _, data = decoder.ReadBytes()
1122
- return int.from_bytes(data, byteorder='little', signed=False)
1176
+ return int.from_bytes(data, byteorder="little", signed=False)
1123
1177
 
1124
1178
  @classmethod
1125
1179
  def FromDecoder(
1126
1180
  cls,
1127
1181
  decoder: utils.LevelDBDecoder,
1128
1182
  key_prefix: KeyPrefix,
1129
- base_offset: int = 0
1183
+ base_offset: int = 0,
1130
1184
  ) -> ExistsEntryKey:
1131
1185
  """Decodes the exists entry key."""
1132
1186
  offset = decoder.stream.tell()
1133
1187
  encoded_user_key = IDBKey.FromDecoder(decoder, offset)
1134
1188
  return cls(
1135
1189
  offset=base_offset + offset,
1136
- key_prefix=key_prefix, encoded_user_key=encoded_user_key)
1190
+ key_prefix=key_prefix,
1191
+ encoded_user_key=encoded_user_key,
1192
+ )
1137
1193
 
1138
1194
 
1139
1195
  @dataclass
@@ -1145,6 +1201,7 @@ class IndexDataKey(BaseIndexedDBKey):
1145
1201
  sequence_number: the sequence number of the data key.
1146
1202
  encoded_primary_key: the encoded primary key.
1147
1203
  """
1204
+
1148
1205
  encoded_user_key: IDBKey
1149
1206
  sequence_number: Optional[int]
1150
1207
  encoded_primary_key: Optional[IDBKey]
@@ -1160,7 +1217,7 @@ class IndexDataKey(BaseIndexedDBKey):
1160
1217
  cls,
1161
1218
  decoder: utils.LevelDBDecoder,
1162
1219
  key_prefix: KeyPrefix,
1163
- base_offset: int = 0
1220
+ base_offset: int = 0,
1164
1221
  ) -> IndexDataKey:
1165
1222
  """Decodes the index data key."""
1166
1223
  offset = decoder.stream.tell()
@@ -1174,7 +1231,8 @@ class IndexDataKey(BaseIndexedDBKey):
1174
1231
  if decoder.NumRemainingBytes() > 0:
1175
1232
  encoded_primary_key_offset = decoder.stream.tell()
1176
1233
  encoded_primary_key = IDBKey.FromDecoder(
1177
- decoder, encoded_primary_key_offset)
1234
+ decoder, encoded_primary_key_offset
1235
+ )
1178
1236
  else:
1179
1237
  encoded_primary_key = None
1180
1238
 
@@ -1183,7 +1241,8 @@ class IndexDataKey(BaseIndexedDBKey):
1183
1241
  encoded_user_key=encoded_user_key,
1184
1242
  sequence_number=sequence_number,
1185
1243
  encoded_primary_key=encoded_primary_key,
1186
- offset=base_offset + offset)
1244
+ offset=base_offset + offset,
1245
+ )
1187
1246
 
1188
1247
 
1189
1248
  @dataclass
@@ -1193,11 +1252,11 @@ class BlobEntryKey(BaseIndexedDBKey):
1193
1252
  Attributes:
1194
1253
  user_key: the user/primary key.
1195
1254
  """
1255
+
1196
1256
  user_key: IDBKey
1197
1257
 
1198
1258
  def DecodeValue(
1199
- self,
1200
- decoder: utils.LevelDBDecoder
1259
+ self, decoder: utils.LevelDBDecoder
1201
1260
  ) -> IndexedDBExternalObject:
1202
1261
  """Decodes the blob entry value."""
1203
1262
  return IndexedDBExternalObject.FromDecoder(decoder)
@@ -1207,14 +1266,15 @@ class BlobEntryKey(BaseIndexedDBKey):
1207
1266
  cls,
1208
1267
  decoder: utils.LevelDBDecoder,
1209
1268
  key_prefix: KeyPrefix,
1210
- base_offset: int = 0
1269
+ base_offset: int = 0,
1211
1270
  ) -> BlobEntryKey:
1212
1271
  """Decodes the blob entry key."""
1213
1272
  offset = decoder.stream.tell()
1214
1273
  user_key = IDBKey.FromDecoder(decoder, offset)
1215
1274
 
1216
- return cls(key_prefix=key_prefix, user_key=user_key,
1217
- offset=base_offset + offset)
1275
+ return cls(
1276
+ key_prefix=key_prefix, user_key=user_key, offset=base_offset + offset
1277
+ )
1218
1278
 
1219
1279
 
1220
1280
  @dataclass
@@ -1246,23 +1306,25 @@ class IndexedDbKey(BaseIndexedDBKey):
1246
1306
  cls,
1247
1307
  decoder: utils.LevelDBDecoder,
1248
1308
  key_prefix: KeyPrefix,
1249
- base_offset: int = 0
1309
+ base_offset: int = 0,
1250
1310
  ) -> Union[
1251
1311
  BlobEntryKey,
1252
1312
  DatabaseMetaDataKey,
1253
1313
  ExistsEntryKey,
1254
1314
  GlobalMetaDataKey,
1255
1315
  IndexDataKey,
1256
- ObjectStoreDataKey]:
1316
+ ObjectStoreDataKey,
1317
+ ]:
1257
1318
  """Decodes the IndexedDB key."""
1258
1319
  key_type = key_prefix.GetKeyPrefixType()
1259
1320
  key_class = cls.METADATA_TYPE_TO_CLASS.get(key_type)
1260
1321
  if not key_class:
1261
- raise errors.ParserError('Unknown KeyPrefixType')
1322
+ raise errors.ParserError("Unknown KeyPrefixType")
1262
1323
  return key_class.FromDecoder(
1263
1324
  decoder=decoder,
1264
- key_prefix=key_prefix, #pytype: disable=bad-return-type
1265
- base_offset=base_offset)
1325
+ key_prefix=key_prefix, # type: ignore[return-value]
1326
+ base_offset=base_offset,
1327
+ )
1266
1328
 
1267
1329
 
1268
1330
  @dataclass
@@ -1274,45 +1336,49 @@ class IndexMetaDataKey(BaseIndexedDBKey):
1274
1336
  index_id: the index ID.
1275
1337
  metadata_type: the metadata key type.
1276
1338
  """
1339
+
1277
1340
  object_store_id: int
1278
1341
  index_id: int
1279
1342
  metadata_type: definitions.IndexMetaDataKeyType
1280
1343
 
1281
1344
  def DecodeValue(
1282
- self,
1283
- decoder: utils.LevelDBDecoder
1345
+ self, decoder: utils.LevelDBDecoder
1284
1346
  ) -> Union[bool, IDBKeyPath, str]:
1285
1347
  """Decodes the index metadata value."""
1286
1348
  if self.metadata_type == definitions.IndexMetaDataKeyType.INDEX_NAME:
1287
1349
  return decoder.DecodeString()[1]
1288
1350
  if self.metadata_type == definitions.IndexMetaDataKeyType.KEY_PATH:
1289
1351
  return IDBKeyPath.FromDecoder(decoder)
1290
- if (self.metadata_type ==
1291
- definitions.IndexMetaDataKeyType.MULTI_ENTRY_FLAG):
1352
+ if self.metadata_type == definitions.IndexMetaDataKeyType.MULTI_ENTRY_FLAG:
1292
1353
  return decoder.DecodeBool()[1]
1293
1354
  if self.metadata_type == definitions.IndexMetaDataKeyType.UNIQUE_FLAG:
1294
1355
  return decoder.DecodeBool()[1]
1295
1356
  raise errors.ParserError(
1296
- f'Unknown index metadata type {self.metadata_type}')
1357
+ f"Unknown index metadata type {self.metadata_type}"
1358
+ )
1297
1359
 
1298
1360
  @classmethod
1299
1361
  def FromDecoder(
1300
1362
  cls,
1301
1363
  decoder: utils.LevelDBDecoder,
1302
1364
  key_prefix: KeyPrefix,
1303
- base_offset: int = 0
1365
+ base_offset: int = 0,
1304
1366
  ) -> IndexMetaDataKey:
1305
1367
  """Decodes the index metadata key."""
1306
1368
  offset, key_type = decoder.DecodeUint8()
1307
1369
  if key_type != definitions.DatabaseMetaDataKeyType.INDEX_META_DATA:
1308
- raise errors.ParserError('Not an IndexMetaDataKey.')
1370
+ raise errors.ParserError("Not an IndexMetaDataKey.")
1309
1371
  _, object_store_id = decoder.DecodeVarint()
1310
1372
  _, index_id = decoder.DecodeVarint()
1311
1373
  _, metadata_bytes = decoder.ReadBytes(1)
1312
1374
  metadata_type = definitions.IndexMetaDataKeyType(metadata_bytes[0])
1313
- return cls(offset=base_offset + offset, key_prefix=key_prefix,
1314
- object_store_id=object_store_id, index_id=index_id,
1315
- metadata_type=metadata_type)
1375
+ return cls(
1376
+ offset=base_offset + offset,
1377
+ key_prefix=key_prefix,
1378
+ object_store_id=object_store_id,
1379
+ index_id=index_id,
1380
+ metadata_type=metadata_type,
1381
+ )
1316
1382
 
1317
1383
 
1318
1384
  @dataclass
@@ -1331,6 +1397,7 @@ class ExternalObjectEntry(utils.FromDecoderMixin):
1331
1397
  last_modified: the last modified time if a blob or file, None otherwise.
1332
1398
  token: the token if a filesystem access handle, None otherwise.
1333
1399
  """
1400
+
1334
1401
  offset: int = field(compare=False)
1335
1402
  object_type: definitions.ExternalObjectType
1336
1403
  blob_number: Optional[int]
@@ -1342,16 +1409,15 @@ class ExternalObjectEntry(utils.FromDecoderMixin):
1342
1409
 
1343
1410
  @classmethod
1344
1411
  def FromDecoder(
1345
- cls,
1346
- decoder: utils.LevelDBDecoder,
1347
- base_offset: int = 0
1412
+ cls, decoder: utils.LevelDBDecoder, base_offset: int = 0
1348
1413
  ) -> ExternalObjectEntry:
1349
1414
  """Decodes the external object entry."""
1350
1415
  offset, object_type_value = decoder.DecodeUint8()
1351
1416
  object_type = definitions.ExternalObjectType(object_type_value)
1352
- if (object_type in
1353
- (definitions.ExternalObjectType.BLOB,
1354
- definitions.ExternalObjectType.FILE)):
1417
+ if object_type in (
1418
+ definitions.ExternalObjectType.BLOB,
1419
+ definitions.ExternalObjectType.FILE,
1420
+ ):
1355
1421
  _, blob_number = decoder.DecodeVarint()
1356
1422
  _, mime_type = decoder.DecodeStringWithLength()
1357
1423
  _, size = decoder.DecodeVarint()
@@ -1363,8 +1429,10 @@ class ExternalObjectEntry(utils.FromDecoderMixin):
1363
1429
  last_modified = None
1364
1430
  token = None
1365
1431
  else:
1366
- if (object_type ==
1367
- definitions.ExternalObjectType.FILE_SYSTEM_ACCESS_HANDLE):
1432
+ if (
1433
+ object_type
1434
+ == definitions.ExternalObjectType.FILE_SYSTEM_ACCESS_HANDLE
1435
+ ):
1368
1436
  _, token = decoder.DecodeBlobWithLength()
1369
1437
  else:
1370
1438
  token = None
@@ -1374,9 +1442,16 @@ class ExternalObjectEntry(utils.FromDecoderMixin):
1374
1442
  filename = None
1375
1443
  last_modified = None
1376
1444
 
1377
- return cls(offset=base_offset + offset, object_type=object_type,
1378
- blob_number=blob_number, mime_type=mime_type, size=size,
1379
- filename=filename, last_modified=last_modified, token=token)
1445
+ return cls(
1446
+ offset=base_offset + offset,
1447
+ object_type=object_type,
1448
+ blob_number=blob_number,
1449
+ mime_type=mime_type,
1450
+ size=size,
1451
+ filename=filename,
1452
+ last_modified=last_modified,
1453
+ token=token,
1454
+ )
1380
1455
 
1381
1456
 
1382
1457
  @dataclass
@@ -1387,14 +1462,13 @@ class IndexedDBExternalObject(utils.FromDecoderMixin):
1387
1462
  offset: the offset of the IndexedDBExternalObject.
1388
1463
  entries: a list of external objects.
1389
1464
  """
1465
+
1390
1466
  offset: int = field(compare=False)
1391
1467
  entries: list[ExternalObjectEntry]
1392
1468
 
1393
1469
  @classmethod
1394
1470
  def FromDecoder(
1395
- cls,
1396
- decoder: utils.LevelDBDecoder,
1397
- base_offset: int = 0
1471
+ cls, decoder: utils.LevelDBDecoder, base_offset: int = 0
1398
1472
  ) -> IndexedDBExternalObject:
1399
1473
  """Decodes the external object."""
1400
1474
  entries = []
@@ -1406,20 +1480,6 @@ class IndexedDBExternalObject(utils.FromDecoderMixin):
1406
1480
  return cls(offset=base_offset + offset, entries=entries)
1407
1481
 
1408
1482
 
1409
- @dataclass
1410
- class ObjectStore:
1411
- """An IndexedDB Object Store.
1412
-
1413
- Attributes:
1414
- id: the object store ID.
1415
- name: the object store name.
1416
- records: the records in the object store.
1417
- """
1418
- id: int
1419
- name: str
1420
- records: list = field(default_factory=list, repr=False)
1421
-
1422
-
1423
1483
  @dataclass
1424
1484
  class IndexedDBRecord:
1425
1485
  """An IndexedDB Record.
@@ -1434,7 +1494,15 @@ class IndexedDBRecord:
1434
1494
  level: the leveldb level, if applicable, None can indicate the record
1435
1495
  originated from a log file or the level could not be determined.
1436
1496
  recovered: True if the record is a recovered record.
1497
+ database_id: the database ID.
1498
+ object_store_id: the object store ID.
1499
+ database_name: the name of the database, if available.
1500
+ object_store_name: the name of the object store, if available.
1501
+ blob: the blob contents, if available.
1502
+ raw_key: the raw key, if available.
1503
+ raw_value: the raw value, if available.
1437
1504
  """
1505
+
1438
1506
  path: str
1439
1507
  offset: int
1440
1508
  key: Any
@@ -1443,46 +1511,70 @@ class IndexedDBRecord:
1443
1511
  type: int
1444
1512
  level: Optional[int]
1445
1513
  recovered: Optional[bool]
1514
+ database_id: int
1515
+ object_store_id: int
1516
+ database_name: Optional[str] = None
1517
+ object_store_name: Optional[str] = None
1518
+ blob: Optional[bytes] = None
1519
+ raw_key: Optional[bytes] = None
1520
+ raw_value: Optional[bytes] = None
1446
1521
 
1447
1522
  @classmethod
1448
1523
  def FromLevelDBRecord(
1449
- cls,
1450
- db_record: record.LevelDBRecord
1524
+ cls, db_record: record.LevelDBRecord, parse_value: bool = True
1451
1525
  ) -> IndexedDBRecord:
1452
1526
  """Returns an IndexedDBRecord from a ParsedInternalKey."""
1453
1527
  idb_key = IndexedDbKey.FromBytes(
1454
- db_record.record.key, base_offset=db_record.record.offset)
1455
- idb_value = idb_key.ParseValue(db_record.record.value)
1528
+ db_record.record.key, base_offset=db_record.record.offset
1529
+ )
1530
+
1531
+ if parse_value:
1532
+ idb_value = idb_key.ParseValue(db_record.record.value)
1533
+ else:
1534
+ idb_value = None
1535
+
1456
1536
  return cls(
1457
1537
  path=db_record.path,
1458
1538
  offset=db_record.record.offset,
1459
1539
  key=idb_key,
1460
1540
  value=idb_value,
1461
- sequence_number=db_record.record.sequence_number if hasattr(
1462
- db_record.record, 'sequence_number') else None,
1541
+ sequence_number=db_record.record.sequence_number
1542
+ if hasattr(db_record.record, "sequence_number")
1543
+ else None,
1463
1544
  type=db_record.record.record_type,
1464
1545
  level=db_record.level,
1465
- recovered=db_record.recovered)
1546
+ recovered=db_record.recovered,
1547
+ database_id=idb_key.key_prefix.database_id,
1548
+ object_store_id=idb_key.key_prefix.object_store_id,
1549
+ database_name=None,
1550
+ object_store_name=None,
1551
+ blob=None,
1552
+ raw_key=db_record.record.key,
1553
+ raw_value=db_record.record.value,
1554
+ )
1466
1555
 
1467
1556
  @classmethod
1468
1557
  def FromFile(
1469
- cls,
1470
- file_path: pathlib.Path
1558
+ cls, file_path: pathlib.Path, parse_value: bool = True
1471
1559
  ) -> Generator[IndexedDBRecord, None, None]:
1472
1560
  """Yields IndexedDBRecords from a file."""
1473
1561
  for db_record in record.LevelDBRecord.FromFile(file_path):
1474
1562
  try:
1475
- yield cls.FromLevelDBRecord(db_record)
1476
- except(
1563
+ yield cls.FromLevelDBRecord(db_record, parse_value=parse_value)
1564
+ except (
1477
1565
  errors.ParserError,
1478
1566
  errors.DecoderError,
1479
- NotImplementedError) as err:
1480
- print((
1481
- 'Error parsing Indexeddb record: '
1482
- f'{err} at offset {db_record.record.offset} in '
1483
- f'{db_record.path}'),
1484
- file=sys.stderr)
1485
- print(f'Traceback: {traceback.format_exc()}', file=sys.stderr)
1567
+ NotImplementedError,
1568
+ ) as err:
1569
+ print(
1570
+ (
1571
+ "Error parsing Indexeddb record: "
1572
+ f"{err} at offset {db_record.record.offset} in "
1573
+ f"{db_record.path}"
1574
+ ),
1575
+ file=sys.stderr,
1576
+ )
1577
+ print(f"Traceback: {traceback.format_exc()}", file=sys.stderr)
1486
1578
 
1487
1579
 
1488
1580
  class FolderReader:
@@ -1502,13 +1594,14 @@ class FolderReader:
1502
1594
  ValueError: if folder_name is None or not a directory.
1503
1595
  """
1504
1596
  if not folder_name or not folder_name.is_dir():
1505
- raise ValueError(f'{folder_name} is None or not a directory')
1597
+ raise ValueError(f"{folder_name} is None or not a directory")
1506
1598
  self.folder_name = folder_name
1507
1599
 
1508
1600
  def GetRecords(
1509
1601
  self,
1510
1602
  use_manifest: bool = False,
1511
- use_sequence_number: bool = False
1603
+ use_sequence_number: bool = False,
1604
+ parse_value: bool = True,
1512
1605
  ) -> Generator[IndexedDBRecord, None, None]:
1513
1606
  """Yield LevelDBRecords.
1514
1607
 
@@ -1516,22 +1609,31 @@ class FolderReader:
1516
1609
  use_manifest: True to use the current manifest in the folder as a means to
1517
1610
  find the active file set.
1518
1611
  use_sequence_number: True to use the sequence number to determine the
1612
+ recovered field.
1613
+ parse_value: True to parse values.
1614
+
1519
1615
  Yields:
1520
1616
  IndexedDBRecord.
1521
1617
  """
1522
1618
  leveldb_folder_reader = record.FolderReader(self.folder_name)
1523
1619
  for leveldb_record in leveldb_folder_reader.GetRecords(
1524
- use_manifest=use_manifest,
1525
- use_sequence_number=use_sequence_number):
1620
+ use_manifest=use_manifest, use_sequence_number=use_sequence_number
1621
+ ):
1526
1622
  try:
1527
- yield IndexedDBRecord.FromLevelDBRecord(leveldb_record)
1528
- except(
1623
+ yield IndexedDBRecord.FromLevelDBRecord(
1624
+ leveldb_record, parse_value=parse_value
1625
+ )
1626
+ except (
1529
1627
  errors.ParserError,
1530
1628
  errors.DecoderError,
1531
- NotImplementedError) as err:
1532
- print((
1533
- 'Error parsing Indexeddb record: '
1534
- f'{err} at offset {leveldb_record.record.offset} in '
1535
- f'{leveldb_record.path}'),
1536
- file=sys.stderr)
1537
- print(f'Traceback: {traceback.format_exc()}', file=sys.stderr)
1629
+ NotImplementedError,
1630
+ ) as err:
1631
+ print(
1632
+ (
1633
+ "Error parsing Indexeddb record: "
1634
+ f"{err} at offset {leveldb_record.record.offset} in "
1635
+ f"{leveldb_record.path}"
1636
+ ),
1637
+ file=sys.stderr,
1638
+ )
1639
+ print(f"Traceback: {traceback.format_exc()}", file=sys.stderr)