dfindexeddb 20240519__py3-none-any.whl → 20241031__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.
- dfindexeddb/indexeddb/chromium/v8.py +30 -10
- dfindexeddb/indexeddb/cli.py +36 -3
- dfindexeddb/indexeddb/firefox/definitions.py +143 -0
- dfindexeddb/indexeddb/firefox/gecko.py +600 -0
- dfindexeddb/indexeddb/firefox/record.py +180 -0
- dfindexeddb/indexeddb/safari/webkit.py +37 -13
- dfindexeddb/indexeddb/types.py +71 -0
- dfindexeddb/leveldb/descriptor.py +2 -1
- dfindexeddb/utils.py +1 -1
- dfindexeddb/version.py +1 -1
- {dfindexeddb-20240519.dist-info → dfindexeddb-20241031.dist-info}/METADATA +12 -6
- {dfindexeddb-20240519.dist-info → dfindexeddb-20241031.dist-info}/RECORD +17 -13
- {dfindexeddb-20240519.dist-info → dfindexeddb-20241031.dist-info}/WHEEL +1 -1
- {dfindexeddb-20240519.dist-info → dfindexeddb-20241031.dist-info}/AUTHORS +0 -0
- {dfindexeddb-20240519.dist-info → dfindexeddb-20241031.dist-info}/LICENSE +0 -0
- {dfindexeddb-20240519.dist-info → dfindexeddb-20241031.dist-info}/entry_points.txt +0 -0
- {dfindexeddb-20240519.dist-info → dfindexeddb-20241031.dist-info}/top_level.txt +0 -0
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
"""Parsers for v8 javascript serialized objects."""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
16
18
|
from dataclasses import dataclass
|
|
17
19
|
from datetime import datetime
|
|
18
20
|
import io
|
|
@@ -25,8 +27,8 @@ from dfindexeddb.indexeddb.chromium import definitions
|
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
@dataclass
|
|
28
|
-
class
|
|
29
|
-
"""A parsed Javascript
|
|
30
|
+
class ArrayBufferView:
|
|
31
|
+
"""A parsed Javascript ArrayBufferView."""
|
|
30
32
|
buffer: bytes
|
|
31
33
|
tag: definitions.V8ArrayBufferViewTag
|
|
32
34
|
offset: int
|
|
@@ -34,15 +36,23 @@ class BufferArrayView:
|
|
|
34
36
|
flags: int
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
@dataclass
|
|
40
|
+
class JSArray:
|
|
38
41
|
"""A parsed Javascript array.
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
properties
|
|
43
|
+
A Javascript array behaves like a Python list but allows assigning arbitrary
|
|
44
|
+
properties. The array is stored in the attribute __array__.
|
|
42
45
|
"""
|
|
46
|
+
def __init__(self):
|
|
47
|
+
self.__array__ = []
|
|
48
|
+
|
|
49
|
+
def Append(self, element: Any):
|
|
50
|
+
"""Appends a new element to the array."""
|
|
51
|
+
self.__array__.append(element)
|
|
43
52
|
|
|
44
53
|
def __repr__(self):
|
|
45
|
-
array_entries = ", ".join(
|
|
54
|
+
array_entries = ", ".join(
|
|
55
|
+
[str(entry) for entry in list(self.__array__)])
|
|
46
56
|
properties = ", ".join(
|
|
47
57
|
f'{key}: {value}' for key, value in self.properties.items())
|
|
48
58
|
return f'[{array_entries}, {properties}]'
|
|
@@ -52,6 +62,11 @@ class JSArray(list):
|
|
|
52
62
|
"""Returns the object properties."""
|
|
53
63
|
return self.__dict__
|
|
54
64
|
|
|
65
|
+
def __eq__(self, other: JSArray):
|
|
66
|
+
return (
|
|
67
|
+
self.__array__ == other.__array__
|
|
68
|
+
and self.properties == other.properties)
|
|
69
|
+
|
|
55
70
|
def __contains__(self, item):
|
|
56
71
|
return item in self.__dict__
|
|
57
72
|
|
|
@@ -194,6 +209,7 @@ class ValueDeserializer:
|
|
|
194
209
|
if tag and tag == definitions.V8SerializationTag.ARRAY_BUFFER_VIEW:
|
|
195
210
|
self._ConsumeTag(tag)
|
|
196
211
|
result = self._ReadJSArrayBufferView(result)
|
|
212
|
+
self.objects[self._GetNextId()] = result
|
|
197
213
|
return result
|
|
198
214
|
|
|
199
215
|
def _ReadObjectInternal(self) -> Tuple[definitions.V8SerializationTag, Any]:
|
|
@@ -385,7 +401,10 @@ class ValueDeserializer:
|
|
|
385
401
|
while self._PeekTag() != end_tag:
|
|
386
402
|
key = self._ReadObject()
|
|
387
403
|
value = self._ReadObject()
|
|
388
|
-
js_object
|
|
404
|
+
if isinstance(js_object, dict):
|
|
405
|
+
js_object[key] = value
|
|
406
|
+
else:
|
|
407
|
+
js_object.properties[key] = value
|
|
389
408
|
num_properties += 1
|
|
390
409
|
self._ConsumeTag(end_tag)
|
|
391
410
|
return num_properties
|
|
@@ -407,7 +426,7 @@ class ValueDeserializer:
|
|
|
407
426
|
js_array = JSArray()
|
|
408
427
|
_, length = self.decoder.DecodeUint32Varint()
|
|
409
428
|
for _ in range(length):
|
|
410
|
-
js_array.
|
|
429
|
+
js_array.Append(Undefined())
|
|
411
430
|
|
|
412
431
|
num_properties = self._ReadJSObjectProperties(
|
|
413
432
|
js_array.__dict__, definitions.V8SerializationTag.END_SPARSE_JS_ARRAY)
|
|
@@ -440,7 +459,7 @@ class ValueDeserializer:
|
|
|
440
459
|
|
|
441
460
|
if self.version < 11 and isinstance(array_object, Undefined):
|
|
442
461
|
continue
|
|
443
|
-
js_array.
|
|
462
|
+
js_array.Append(array_object)
|
|
444
463
|
|
|
445
464
|
num_properties = self._ReadJSObjectProperties(
|
|
446
465
|
js_array.__dict__, definitions.V8SerializationTag.END_DENSE_JS_ARRAY)
|
|
@@ -571,6 +590,7 @@ class ValueDeserializer:
|
|
|
571
590
|
if is_resizable:
|
|
572
591
|
_, max_byte_length = self.decoder.DecodeUint32Varint()
|
|
573
592
|
if byte_length > max_byte_length:
|
|
593
|
+
self.objects[next_id] = array_buffer
|
|
574
594
|
return array_buffer
|
|
575
595
|
if byte_length:
|
|
576
596
|
_, array_buffer = self.decoder.ReadBytes(byte_length)
|
|
@@ -589,7 +609,7 @@ class ValueDeserializer:
|
|
|
589
609
|
else:
|
|
590
610
|
flags = 0
|
|
591
611
|
|
|
592
|
-
return
|
|
612
|
+
return ArrayBufferView(
|
|
593
613
|
buffer=buffer,
|
|
594
614
|
tag=definitions.V8ArrayBufferViewTag(tag[0]),
|
|
595
615
|
offset=byte_offset,
|
dfindexeddb/indexeddb/cli.py
CHANGED
|
@@ -25,6 +25,8 @@ from dfindexeddb import version
|
|
|
25
25
|
from dfindexeddb.indexeddb.chromium import blink
|
|
26
26
|
from dfindexeddb.indexeddb.chromium import record as chromium_record
|
|
27
27
|
from dfindexeddb.indexeddb.chromium import v8
|
|
28
|
+
from dfindexeddb.indexeddb.firefox import gecko
|
|
29
|
+
from dfindexeddb.indexeddb.firefox import record as firefox_record
|
|
28
30
|
from dfindexeddb.indexeddb.safari import record as safari_record
|
|
29
31
|
|
|
30
32
|
|
|
@@ -39,7 +41,7 @@ class Encoder(json.JSONEncoder):
|
|
|
39
41
|
if dataclasses.is_dataclass(o):
|
|
40
42
|
o_dict = utils.asdict(o)
|
|
41
43
|
return o_dict
|
|
42
|
-
if isinstance(o, bytes):
|
|
44
|
+
if isinstance(o, (bytes, bytearray)):
|
|
43
45
|
out = []
|
|
44
46
|
for x in o:
|
|
45
47
|
if chr(x) not in _VALID_PRINTABLE_CHARACTERS:
|
|
@@ -51,6 +53,8 @@ class Encoder(json.JSONEncoder):
|
|
|
51
53
|
return o.isoformat()
|
|
52
54
|
if isinstance(o, v8.Undefined):
|
|
53
55
|
return "<undefined>"
|
|
56
|
+
if isinstance(o, v8.JSArray):
|
|
57
|
+
return o.__dict__
|
|
54
58
|
if isinstance(o, v8.Null):
|
|
55
59
|
return "<null>"
|
|
56
60
|
if isinstance(o, set):
|
|
@@ -73,13 +77,21 @@ def _Output(structure, output):
|
|
|
73
77
|
|
|
74
78
|
|
|
75
79
|
def BlinkCommand(args):
|
|
76
|
-
"""The CLI for processing a file as a blink value."""
|
|
80
|
+
"""The CLI for processing a file as a blink-encoded value."""
|
|
77
81
|
with open(args.source, 'rb') as fd:
|
|
78
82
|
buffer = fd.read()
|
|
79
83
|
blink_value = blink.V8ScriptValueDecoder.FromBytes(buffer)
|
|
80
84
|
_Output(blink_value, output=args.output)
|
|
81
85
|
|
|
82
86
|
|
|
87
|
+
def GeckoCommand(args):
|
|
88
|
+
"""The CLI for processing a file as a gecko-encoded value."""
|
|
89
|
+
with open(args.source, 'rb') as fd:
|
|
90
|
+
buffer = fd.read()
|
|
91
|
+
blink_value = gecko.JSStructuredCloneDecoder.FromBytes(buffer)
|
|
92
|
+
_Output(blink_value, output=args.output)
|
|
93
|
+
|
|
94
|
+
|
|
83
95
|
def DbCommand(args):
|
|
84
96
|
"""The CLI for processing a directory as IndexedDB."""
|
|
85
97
|
if args.format in ('chrome', 'chromium'):
|
|
@@ -88,6 +100,9 @@ def DbCommand(args):
|
|
|
88
100
|
use_manifest=args.use_manifest,
|
|
89
101
|
use_sequence_number=args.use_sequence_number):
|
|
90
102
|
_Output(db_record, output=args.output)
|
|
103
|
+
elif args.format == 'firefox':
|
|
104
|
+
for db_record in firefox_record.FileReader(args.source).Records():
|
|
105
|
+
_Output(db_record, output=args.output)
|
|
91
106
|
elif args.format == 'safari':
|
|
92
107
|
for db_record in safari_record.FileReader(args.source).Records():
|
|
93
108
|
_Output(db_record, output=args.output)
|
|
@@ -133,6 +148,24 @@ def App():
|
|
|
133
148
|
help='Output format. Default is json')
|
|
134
149
|
parser_blink.set_defaults(func=BlinkCommand)
|
|
135
150
|
|
|
151
|
+
parser_gecko = subparsers.add_parser(
|
|
152
|
+
'gecko', help='Parse a file as a gecko-encoded value.')
|
|
153
|
+
parser_gecko.add_argument(
|
|
154
|
+
'-s', '--source',
|
|
155
|
+
required=True,
|
|
156
|
+
type=pathlib.Path,
|
|
157
|
+
help='The source file.')
|
|
158
|
+
parser_gecko.add_argument(
|
|
159
|
+
'-o',
|
|
160
|
+
'--output',
|
|
161
|
+
choices=[
|
|
162
|
+
'json',
|
|
163
|
+
'jsonl',
|
|
164
|
+
'repr'],
|
|
165
|
+
default='json',
|
|
166
|
+
help='Output format. Default is json')
|
|
167
|
+
parser_gecko.set_defaults(func=GeckoCommand)
|
|
168
|
+
|
|
136
169
|
parser_db = subparsers.add_parser(
|
|
137
170
|
'db', help='Parse a directory as IndexedDB.')
|
|
138
171
|
parser_db.add_argument(
|
|
@@ -156,7 +189,7 @@ def App():
|
|
|
156
189
|
parser_db.add_argument(
|
|
157
190
|
'--format',
|
|
158
191
|
required=True,
|
|
159
|
-
choices=['chromium', 'chrome', 'safari'],
|
|
192
|
+
choices=['chromium', 'chrome', 'firefox', 'safari'],
|
|
160
193
|
help='The type of IndexedDB to parse.')
|
|
161
194
|
parser_db.add_argument(
|
|
162
195
|
'-o',
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright 2024 Google LLC
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
"""Definitions for Firefox IndexedDB."""
|
|
16
|
+
from enum import IntEnum
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class IndexedDBKeyType(IntEnum):
|
|
20
|
+
"""IndexedDB Key Types."""
|
|
21
|
+
TERMINATOR = 0
|
|
22
|
+
FLOAT = 0x10
|
|
23
|
+
DATE = 0x20
|
|
24
|
+
STRING = 0x30
|
|
25
|
+
BINARY = 0x40
|
|
26
|
+
ARRAY = 0x50
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
MAX_ARRAY_COLLAPSE = 3
|
|
30
|
+
MAX_RECURSION_DEPTH = 64
|
|
31
|
+
MAX_LENGTH = (1 << 30) - 2
|
|
32
|
+
ONE_BYTE_LIMIT = 0x7E
|
|
33
|
+
TWO_BYTE_LIMIT = 0x3FFF + 0x7F
|
|
34
|
+
ONE_BYTE_ADJUST = 1
|
|
35
|
+
TWO_BYTE_ADJUST = -0x7F
|
|
36
|
+
THREE_BYTE_SHIFT = 6
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class StructuredDataType(IntEnum):
|
|
40
|
+
"""Structured Data Types."""
|
|
41
|
+
FLOAT_MAX = 0xFFF00000
|
|
42
|
+
HEADER = 0xFFF10000
|
|
43
|
+
NULL = 0xFFFF0000
|
|
44
|
+
UNDEFINED = 0xFFFF0001
|
|
45
|
+
BOOLEAN = 0xFFFF0002
|
|
46
|
+
INT32 = 0xFFFF0003
|
|
47
|
+
STRING = 0xFFFF0004
|
|
48
|
+
DATE_OBJECT = 0xFFFF0005
|
|
49
|
+
REGEXP_OBJECT = 0xFFFF0006
|
|
50
|
+
ARRAY_OBJECT = 0xFFFF0007
|
|
51
|
+
OBJECT_OBJECT = 0xFFFF0008
|
|
52
|
+
ARRAY_BUFFER_OBJECT_V2 = 0xFFFF0009
|
|
53
|
+
BOOLEAN_OBJECT = 0xFFFF000A
|
|
54
|
+
STRING_OBJECT = 0xFFFF000B
|
|
55
|
+
NUMBER_OBJECT = 0xFFFF000C
|
|
56
|
+
BACK_REFERENCE_OBJECT = 0xFFFF000D
|
|
57
|
+
DO_NOT_USE_1 = 0xFFFF000E
|
|
58
|
+
DO_NOT_USE_2 = 0xFFFF000F
|
|
59
|
+
TYPED_ARRAY_OBJECT_V2 = 0xFFFF0010
|
|
60
|
+
MAP_OBJECT = 0xFFFF0011
|
|
61
|
+
SET_OBJECT = 0xFFFF0012
|
|
62
|
+
END_OF_KEYS = 0xFFFF0013
|
|
63
|
+
DO_NOT_USE_3 = 0xFFFF0014
|
|
64
|
+
DATA_VIEW_OBJECT_V2 = 0xFFFF0015
|
|
65
|
+
SAVED_FRAME_OBJECT = 0xFFFF0016
|
|
66
|
+
JSPRINCIPALS = 0xFFFF0017
|
|
67
|
+
NULL_JSPRINCIPALS = 0xFFFF0018
|
|
68
|
+
RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_SYSTEM = 0xFFFF0019
|
|
69
|
+
RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_NOT_SYSTEM = 0xFFFF001A
|
|
70
|
+
SHARED_ARRAY_BUFFER_OBJECT = 0xFFFF001B
|
|
71
|
+
SHARED_WASM_MEMORY_OBJECT = 0xFFFF001C
|
|
72
|
+
BIGINT = 0xFFFF001D
|
|
73
|
+
BIGINT_OBJECT = 0xFFFF001E
|
|
74
|
+
ARRAY_BUFFER_OBJECT = 0xFFFF001F
|
|
75
|
+
TYPED_ARRAY_OBJECT = 0xFFFF0020
|
|
76
|
+
DATA_VIEW_OBJECT = 0xFFFF0021
|
|
77
|
+
ERROR_OBJECT = 0xFFFF0022
|
|
78
|
+
RESIZABLE_ARRAY_BUFFER_OBJECT = 0xFFFF0023
|
|
79
|
+
GROWABLE_SHARED_ARRAY_BUFFER_OBJECT = 0xFFFF0024
|
|
80
|
+
TYPED_ARRAY_V1_INT8 = 0xFFFF0100
|
|
81
|
+
TYPED_ARRAY_V1_UINT8 = 0xFFFF0101
|
|
82
|
+
TYPED_ARRAY_V1_INT16 = 0xFFFF0102
|
|
83
|
+
TYPED_ARRAY_V1_UINT16 = 0xFFFF0103
|
|
84
|
+
TYPED_ARRAY_V1_INT32 = 0xFFFF0104
|
|
85
|
+
TYPED_ARRAY_V1_UINT32 = 0xFFFF0105
|
|
86
|
+
TYPED_ARRAY_V1_FLOAT32 = 0xFFFF0106
|
|
87
|
+
TYPED_ARRAY_V1_FLOAT64 = 0xFFFF0107
|
|
88
|
+
TYPED_ARRAY_V1_UINT8_CLAMPED = 0xFFFF0108
|
|
89
|
+
TRANSFER_MAP_HEADER = 0xFFFF0200
|
|
90
|
+
TRANSFER_MAP_PENDING_ENTRY = 0xFFFF0201
|
|
91
|
+
TRANSFER_MAP_ARRAY_BUFFER = 0xFFFF0202
|
|
92
|
+
TRANSFER_MAP_STORED_ARRAY_BUFFER = 0xFFFF0203
|
|
93
|
+
TRANSFER_MAP_END_OF_BUILTIN_TYPES = 0xFFFF0204
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class StructuredCloneTags(IntEnum):
|
|
97
|
+
"""Structured Clone Tags."""
|
|
98
|
+
BLOB = 0xFFFF8001
|
|
99
|
+
FILE_WITHOUT_LASTMODIFIEDDATE = 0xFFFF8002
|
|
100
|
+
FILELIST = 0xFFFF8003
|
|
101
|
+
MUTABLEFILE = 0xFFFF8004
|
|
102
|
+
FILE = 0xFFFF8005
|
|
103
|
+
WASM_MODULE = 0xFFFF8006
|
|
104
|
+
IMAGEDATA = 0xFFFF8007
|
|
105
|
+
DOMPOINT = 0xFFFF8008
|
|
106
|
+
DOMPOINTREADONLY = 0xFFFF8009
|
|
107
|
+
CRYPTOKEY = 0xFFFF800A
|
|
108
|
+
NULL_PRINCIPAL = 0xFFFF800B
|
|
109
|
+
SYSTEM_PRINCIPAL = 0xFFFF800C
|
|
110
|
+
CONTENT_PRINCIPAL = 0xFFFF800D
|
|
111
|
+
DOMQUAD = 0xFFFF800E
|
|
112
|
+
RTCCERTIFICATE = 0xFFFF800F
|
|
113
|
+
DOMRECT = 0xFFFF8010
|
|
114
|
+
DOMRECTREADONLY = 0xFFFF8011
|
|
115
|
+
EXPANDED_PRINCIPAL = 0xFFFF8012
|
|
116
|
+
DOMMATRIX = 0xFFFF8013
|
|
117
|
+
URLSEARCHPARAMS = 0xFFFF8014
|
|
118
|
+
DOMMATRIXREADONLY = 0xFFFF8015
|
|
119
|
+
DOMEXCEPTION = 0xFFFF80016
|
|
120
|
+
EMPTY_SLOT_9 = 0xFFFF8017
|
|
121
|
+
STRUCTUREDCLONETESTER = 0xFFFF8018
|
|
122
|
+
FILESYSTEMHANDLE = 0xFFFF8019
|
|
123
|
+
FILESYSTEMFILEHANDLE = 0xFFFF801A
|
|
124
|
+
FILESYSTEMDIRECTORYHANDLE = 0xFFFF801B
|
|
125
|
+
IMAGEBITMAP = 0xFFFF801C
|
|
126
|
+
MAP_MESSAGEPORT = 0xFFFF801D
|
|
127
|
+
FORMDATA = 0xFFFF801E
|
|
128
|
+
CANVAS = 0xFFFF801F # This tag is for OffscreenCanvas.
|
|
129
|
+
DIRECTORY = 0xFFFF8020
|
|
130
|
+
INPUTSTREAM = 0xFFFF8021
|
|
131
|
+
STRUCTURED_CLONE_HOLDER = 0xFFFF8022
|
|
132
|
+
BROWSING_CONTEXT = 0xFFFF8023
|
|
133
|
+
CLONED_ERROR_OBJECT = 0xFFFF8024
|
|
134
|
+
READABLESTREAM = 0xFFFF8025
|
|
135
|
+
WRITABLESTREAM = 0xFFFF8026
|
|
136
|
+
TRANSFORMSTREAM = 0xFFFF8027
|
|
137
|
+
VIDEOFRAME = 0xFFFF8028
|
|
138
|
+
ENCODEDVIDEOCHUNK = 0xFFFF8029
|
|
139
|
+
AUDIODATA = 0xFFFF8030
|
|
140
|
+
ENCODEDAUDIOCHUNK = 0xFFFF8031
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
FRAME_HEADER = b'\xff\x06\x00\x00sNaPpY'
|