dfindexeddb 20241031__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.
- dfindexeddb/indexeddb/chromium/blink.py +116 -74
- dfindexeddb/indexeddb/chromium/definitions.py +152 -124
- dfindexeddb/indexeddb/chromium/record.py +536 -348
- dfindexeddb/indexeddb/chromium/v8.py +112 -141
- dfindexeddb/indexeddb/cli.py +125 -114
- dfindexeddb/indexeddb/firefox/definitions.py +7 -4
- dfindexeddb/indexeddb/firefox/gecko.py +103 -79
- dfindexeddb/indexeddb/firefox/record.py +66 -24
- dfindexeddb/indexeddb/safari/definitions.py +12 -10
- dfindexeddb/indexeddb/safari/record.py +68 -51
- dfindexeddb/indexeddb/safari/webkit.py +112 -189
- dfindexeddb/indexeddb/types.py +5 -2
- dfindexeddb/leveldb/cli.py +146 -131
- dfindexeddb/leveldb/definitions.py +6 -2
- dfindexeddb/leveldb/descriptor.py +75 -45
- dfindexeddb/leveldb/ldb.py +39 -30
- dfindexeddb/leveldb/log.py +44 -27
- dfindexeddb/leveldb/plugins/chrome_notifications.py +30 -18
- dfindexeddb/leveldb/plugins/interface.py +5 -6
- dfindexeddb/leveldb/plugins/manager.py +11 -10
- dfindexeddb/leveldb/record.py +71 -62
- dfindexeddb/leveldb/utils.py +21 -13
- dfindexeddb/utils.py +35 -30
- dfindexeddb/version.py +2 -2
- dfindexeddb-20251109.dist-info/METADATA +222 -0
- dfindexeddb-20251109.dist-info/RECORD +40 -0
- {dfindexeddb-20241031.dist-info → dfindexeddb-20251109.dist-info}/WHEEL +1 -1
- dfindexeddb-20241031.dist-info/AUTHORS +0 -12
- dfindexeddb-20241031.dist-info/METADATA +0 -424
- dfindexeddb-20241031.dist-info/RECORD +0 -41
- {dfindexeddb-20241031.dist-info → dfindexeddb-20251109.dist-info}/entry_points.txt +0 -0
- {dfindexeddb-20241031.dist-info → dfindexeddb-20251109.dist-info/licenses}/LICENSE +0 -0
- {dfindexeddb-20241031.dist-info → dfindexeddb-20251109.dist-info}/top_level.txt +0 -0
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
"""Parsers for WebKit encoded JavaScript values."""
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
-
from dataclasses import dataclass
|
|
19
|
-
from datetime import datetime
|
|
20
18
|
import io
|
|
21
19
|
import plistlib
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
from datetime import datetime
|
|
22
22
|
from typing import Any, Dict, List, Tuple, Union
|
|
23
23
|
|
|
24
|
-
from dfindexeddb import errors
|
|
25
|
-
from dfindexeddb import
|
|
24
|
+
from dfindexeddb import errors, utils
|
|
25
|
+
from dfindexeddb.indexeddb import types
|
|
26
26
|
from dfindexeddb.indexeddb.safari import definitions
|
|
27
27
|
|
|
28
28
|
|
|
@@ -36,6 +36,7 @@ class ArrayBufferView:
|
|
|
36
36
|
offset: the offset of the view.
|
|
37
37
|
length: the length of the view.
|
|
38
38
|
"""
|
|
39
|
+
|
|
39
40
|
array_buffer_view_subtag: definitions.ArrayBufferViewSubtag
|
|
40
41
|
buffer: bytes
|
|
41
42
|
offset: int
|
|
@@ -50,6 +51,7 @@ class ResizableArrayBuffer:
|
|
|
50
51
|
buffer: the buffer.
|
|
51
52
|
max_length: the maximum length of the buffer (for resizing).
|
|
52
53
|
"""
|
|
54
|
+
|
|
53
55
|
buffer: bytes
|
|
54
56
|
max_length: int
|
|
55
57
|
|
|
@@ -65,6 +67,7 @@ class FileData:
|
|
|
65
67
|
name: the file name.
|
|
66
68
|
last_modified: the last modified timestamp.
|
|
67
69
|
"""
|
|
70
|
+
|
|
68
71
|
path: str
|
|
69
72
|
url: str
|
|
70
73
|
type: str
|
|
@@ -79,103 +82,8 @@ class FileList:
|
|
|
79
82
|
Attributes:
|
|
80
83
|
files: the list of files.
|
|
81
84
|
"""
|
|
82
|
-
files: List[FileData]
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
class JSArray:
|
|
86
|
-
"""A parsed Javascript array.
|
|
87
|
-
|
|
88
|
-
A Javascript array behaves like a Python list but allows assigning arbitrary
|
|
89
|
-
properties. The array is stored in the attribute __array__.
|
|
90
|
-
"""
|
|
91
|
-
def __init__(self):
|
|
92
|
-
self.__array__ = []
|
|
93
|
-
|
|
94
|
-
def Append(self, element: Any):
|
|
95
|
-
"""Appends a new element to the array."""
|
|
96
|
-
self.__array__.append(element)
|
|
97
|
-
|
|
98
|
-
def __repr__(self):
|
|
99
|
-
array_entries = ", ".join(
|
|
100
|
-
[str(entry) for entry in list(self.__array__)])
|
|
101
|
-
properties = ", ".join(
|
|
102
|
-
f'{key}: {value}' for key, value in self.properties.items())
|
|
103
|
-
return f'[{array_entries}, {properties}]'
|
|
104
|
-
|
|
105
|
-
@property
|
|
106
|
-
def properties(self) -> Dict[str, Any]:
|
|
107
|
-
"""Returns the object properties."""
|
|
108
|
-
return self.__dict__
|
|
109
|
-
|
|
110
|
-
def __eq__(self, other: JSArray):
|
|
111
|
-
return (
|
|
112
|
-
self.__array__ == other.__array__
|
|
113
|
-
and self.properties == other.properties)
|
|
114
|
-
|
|
115
|
-
def __contains__(self, item):
|
|
116
|
-
return item in self.__dict__
|
|
117
|
-
|
|
118
|
-
def __getitem__(self, name):
|
|
119
|
-
return self.__dict__[name]
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
class JSSet:
|
|
123
|
-
"""A parsed Javascript set.
|
|
124
|
-
|
|
125
|
-
A Javascript set behaves like a Python set but allows assigning arbitrary
|
|
126
|
-
properties. The array is stored in the attribute __set__.
|
|
127
|
-
"""
|
|
128
|
-
def __init__(self):
|
|
129
|
-
self.__set__ = set()
|
|
130
|
-
|
|
131
|
-
def Add(self, element: Any):
|
|
132
|
-
"""Adds a new element to the set."""
|
|
133
|
-
self.__set__.add(element)
|
|
134
|
-
|
|
135
|
-
def __repr__(self):
|
|
136
|
-
array_entries = ", ".join(
|
|
137
|
-
[str(entry) for entry in list(self.__set__)])
|
|
138
|
-
properties = ", ".join(
|
|
139
|
-
f'{key}: {value}' for key, value in self.properties.items())
|
|
140
|
-
return f'[{array_entries}, {properties}]'
|
|
141
|
-
|
|
142
|
-
@property
|
|
143
|
-
def properties(self) -> Dict[str, Any]:
|
|
144
|
-
"""Returns the object properties."""
|
|
145
|
-
return self.__dict__
|
|
146
|
-
|
|
147
|
-
def __eq__(self, other: JSSet):
|
|
148
|
-
return (
|
|
149
|
-
self.__set__ == other.__set__
|
|
150
|
-
and self.properties == other.properties)
|
|
151
|
-
|
|
152
|
-
def __contains__(self, item):
|
|
153
|
-
return item in self.__dict__
|
|
154
|
-
|
|
155
|
-
def __getitem__(self, name):
|
|
156
|
-
return self.__dict__[name]
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
@dataclass
|
|
160
|
-
class Null:
|
|
161
|
-
"""A parsed JavaScript Null."""
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
@dataclass
|
|
165
|
-
class RegExp:
|
|
166
|
-
"""A parsed JavaScript RegExp.
|
|
167
|
-
|
|
168
|
-
Attributes:
|
|
169
|
-
pattern: the pattern.
|
|
170
|
-
flags: the flags.
|
|
171
|
-
"""
|
|
172
|
-
pattern: str
|
|
173
|
-
flags: str
|
|
174
|
-
|
|
175
85
|
|
|
176
|
-
|
|
177
|
-
class Undefined:
|
|
178
|
-
"""A parsed JavaScript undef."""
|
|
86
|
+
files: List[FileData]
|
|
179
87
|
|
|
180
88
|
|
|
181
89
|
@dataclass
|
|
@@ -187,13 +95,15 @@ class IDBKeyData(utils.FromDecoderMixin):
|
|
|
187
95
|
key_type: the IDB Key Type.
|
|
188
96
|
data: the key data.
|
|
189
97
|
"""
|
|
98
|
+
|
|
190
99
|
offset: int
|
|
191
100
|
key_type: definitions.SIDBKeyType
|
|
192
|
-
data: Union[float, datetime, str, bytes, list]
|
|
101
|
+
data: Union[float, datetime, str, bytes, list[Any], None]
|
|
193
102
|
|
|
194
103
|
@classmethod
|
|
195
104
|
def FromDecoder(
|
|
196
|
-
cls, decoder: utils.StreamDecoder, base_offset: int = 0
|
|
105
|
+
cls, decoder: utils.StreamDecoder, base_offset: int = 0
|
|
106
|
+
) -> IDBKeyData:
|
|
197
107
|
"""Decodes an IDBKeyData from the current position of decoder.
|
|
198
108
|
|
|
199
109
|
Refer to IDBSerialization.cpp for the encoding scheme.
|
|
@@ -208,18 +118,22 @@ class IDBKeyData(utils.FromDecoderMixin):
|
|
|
208
118
|
ParserError: when the key version is not found or an unknown key type is
|
|
209
119
|
encountered or an old-style PropertyList key type is found.
|
|
210
120
|
"""
|
|
211
|
-
|
|
121
|
+
|
|
122
|
+
def _DecodeKeyBuffer(
|
|
123
|
+
key_type: definitions.SIDBKeyType,
|
|
124
|
+
) -> Union[float, datetime, str, bytes, list[Any], None]:
|
|
125
|
+
data: Union[float, datetime, str, bytes, list[Any], None] = None
|
|
212
126
|
if key_type == definitions.SIDBKeyType.MIN:
|
|
213
127
|
data = None
|
|
214
128
|
if key_type == definitions.SIDBKeyType.NUMBER:
|
|
215
129
|
_, data = decoder.DecodeDouble()
|
|
216
130
|
elif key_type == definitions.SIDBKeyType.DATE:
|
|
217
131
|
_, timestamp = decoder.DecodeDouble()
|
|
218
|
-
data = datetime.utcfromtimestamp(timestamp/1000)
|
|
132
|
+
data = datetime.utcfromtimestamp(timestamp / 1000)
|
|
219
133
|
elif key_type == definitions.SIDBKeyType.STRING:
|
|
220
134
|
_, length = decoder.DecodeUint32()
|
|
221
|
-
_, raw_data = decoder.ReadBytes(length*2)
|
|
222
|
-
data = raw_data.decode(
|
|
135
|
+
_, raw_data = decoder.ReadBytes(length * 2)
|
|
136
|
+
data = raw_data.decode("utf-16-le")
|
|
223
137
|
elif key_type == definitions.SIDBKeyType.BINARY:
|
|
224
138
|
_, length = decoder.DecodeUint32()
|
|
225
139
|
_, data = decoder.ReadBytes(length)
|
|
@@ -227,33 +141,30 @@ class IDBKeyData(utils.FromDecoderMixin):
|
|
|
227
141
|
_, length = decoder.DecodeUint64()
|
|
228
142
|
data = []
|
|
229
143
|
for _ in range(length):
|
|
230
|
-
_,
|
|
231
|
-
element = _DecodeKeyBuffer(
|
|
144
|
+
_, next_key_type = decoder.DecodeUint8()
|
|
145
|
+
element = _DecodeKeyBuffer(definitions.SIDBKeyType(next_key_type))
|
|
232
146
|
data.append(element)
|
|
233
147
|
else:
|
|
234
|
-
raise errors.ParserError(
|
|
148
|
+
raise errors.ParserError("Unknown definitions.SIDBKeyType found.")
|
|
235
149
|
return data
|
|
236
150
|
|
|
237
151
|
offset, version_header = decoder.DecodeUint8()
|
|
238
|
-
if version_header != definitions.
|
|
239
|
-
raise errors.ParserError(
|
|
152
|
+
if version_header != definitions.SIDB_KEY_VERSION:
|
|
153
|
+
raise errors.ParserError("SIDBKeyVersion not found.")
|
|
240
154
|
|
|
241
155
|
_, raw_key_type = decoder.DecodeUint8()
|
|
242
|
-
key_type = definitions.SIDBKeyType(raw_key_type)
|
|
243
156
|
|
|
244
157
|
# "Old-style key is characterized by this magic character that
|
|
245
158
|
# begins serialized PropertyLists
|
|
246
|
-
if
|
|
247
|
-
raise errors.ParserError(
|
|
159
|
+
if raw_key_type == ord(b"b"):
|
|
160
|
+
raise errors.ParserError("Old-style PropertyList key type found.")
|
|
161
|
+
key_type = definitions.SIDBKeyType(raw_key_type)
|
|
248
162
|
data = _DecodeKeyBuffer(key_type)
|
|
249
163
|
|
|
250
|
-
return cls(
|
|
251
|
-
offset=offset+base_offset,
|
|
252
|
-
key_type=key_type,
|
|
253
|
-
data=data)
|
|
164
|
+
return cls(offset=offset + base_offset, key_type=key_type, data=data)
|
|
254
165
|
|
|
255
166
|
|
|
256
|
-
class SerializedScriptValueDecoder
|
|
167
|
+
class SerializedScriptValueDecoder:
|
|
257
168
|
"""Decodes a Serialized Script Value from a stream of bytes.
|
|
258
169
|
|
|
259
170
|
Attributes:
|
|
@@ -262,16 +173,17 @@ class SerializedScriptValueDecoder():
|
|
|
262
173
|
constant_pool: the constant pool.
|
|
263
174
|
object_pool: the object pool.
|
|
264
175
|
"""
|
|
176
|
+
|
|
265
177
|
def __init__(self, stream: io.BytesIO):
|
|
266
178
|
self.decoder = utils.StreamDecoder(stream)
|
|
267
|
-
self.version =
|
|
268
|
-
self.constant_pool = []
|
|
269
|
-
self.object_pool = []
|
|
179
|
+
self.version: int = 0
|
|
180
|
+
self.constant_pool: list[str] = []
|
|
181
|
+
self.object_pool: list[Any] = []
|
|
270
182
|
|
|
271
183
|
def PeekTag(self) -> int:
|
|
272
184
|
"""Peeks a tag from the current position."""
|
|
273
185
|
_, peeked_bytes = self.decoder.PeekBytes(4)
|
|
274
|
-
return int.from_bytes(peeked_bytes, byteorder=
|
|
186
|
+
return int.from_bytes(peeked_bytes, byteorder="little")
|
|
275
187
|
|
|
276
188
|
def PeekSerializationTag(self) -> definitions.SerializationTag:
|
|
277
189
|
"""Peeks a SerializationTag from the current position.
|
|
@@ -284,7 +196,7 @@ class SerializedScriptValueDecoder():
|
|
|
284
196
|
return definitions.SerializationTag(terminal_byte[0])
|
|
285
197
|
except ValueError as error:
|
|
286
198
|
raise errors.ParserError(
|
|
287
|
-
f
|
|
199
|
+
f"Invalid SerializationTag {terminal_byte!r} at offset {offset}"
|
|
288
200
|
) from error
|
|
289
201
|
|
|
290
202
|
def DecodeSerializationTag(self) -> Tuple[int, definitions.SerializationTag]:
|
|
@@ -301,9 +213,10 @@ class SerializedScriptValueDecoder():
|
|
|
301
213
|
return offset, definitions.SerializationTag(terminal_byte)
|
|
302
214
|
except ValueError as error:
|
|
303
215
|
raise errors.ParserError(
|
|
304
|
-
f
|
|
216
|
+
f"Invalid terminal {terminal_byte} at offset {offset}"
|
|
217
|
+
) from error
|
|
305
218
|
|
|
306
|
-
def DecodeArray(self) -> JSArray:
|
|
219
|
+
def DecodeArray(self) -> types.JSArray:
|
|
307
220
|
"""Decodes an Array value.
|
|
308
221
|
|
|
309
222
|
Returns:
|
|
@@ -313,34 +226,34 @@ class SerializedScriptValueDecoder():
|
|
|
313
226
|
ParserError if an invalid Terminator tag was found.
|
|
314
227
|
"""
|
|
315
228
|
_, length = self.decoder.DecodeUint32()
|
|
316
|
-
array = JSArray()
|
|
229
|
+
array = types.JSArray()
|
|
317
230
|
self.object_pool.append(array)
|
|
318
231
|
for _ in range(length):
|
|
319
232
|
_, _ = self.decoder.DecodeUint32()
|
|
320
233
|
_, value = self.DecodeValue()
|
|
321
|
-
array.
|
|
234
|
+
array.values.append(value)
|
|
322
235
|
|
|
323
236
|
offset, terminator_tag = self.decoder.DecodeUint32()
|
|
324
|
-
if terminator_tag != definitions.
|
|
325
|
-
raise errors.ParserError(f
|
|
237
|
+
if terminator_tag != definitions.TERMINATOR_TAG:
|
|
238
|
+
raise errors.ParserError(f"Terminator tag not found at offset {offset}.")
|
|
326
239
|
|
|
327
240
|
offset, tag = self.decoder.DecodeUint32()
|
|
328
|
-
if tag == definitions.
|
|
329
|
-
while tag != definitions.
|
|
241
|
+
if tag == definitions.NON_INDEX_PROPERTIES_TAG:
|
|
242
|
+
while tag != definitions.TERMINATOR_TAG:
|
|
330
243
|
name = self.DecodeStringData()
|
|
331
244
|
_, value = self.DecodeValue()
|
|
332
245
|
_, tag = self.decoder.DecodeUint32()
|
|
333
246
|
array.properties[name] = value
|
|
334
|
-
elif tag != definitions.
|
|
335
|
-
raise errors.ParserError(f
|
|
247
|
+
elif tag != definitions.TERMINATOR_TAG:
|
|
248
|
+
raise errors.ParserError(f"Terminator tag not found at offset {offset}.")
|
|
336
249
|
return array
|
|
337
250
|
|
|
338
251
|
def DecodeObject(self) -> Dict[str, Any]:
|
|
339
252
|
"""Decodes an Object value."""
|
|
340
253
|
tag = self.PeekTag()
|
|
341
|
-
js_object = {}
|
|
254
|
+
js_object: dict[str, Any] = {}
|
|
342
255
|
self.object_pool.append(js_object)
|
|
343
|
-
while tag != definitions.
|
|
256
|
+
while tag != definitions.TERMINATOR_TAG:
|
|
344
257
|
name = self.DecodeStringData()
|
|
345
258
|
_, value = self.DecodeValue()
|
|
346
259
|
js_object[name] = value
|
|
@@ -362,45 +275,46 @@ class SerializedScriptValueDecoder():
|
|
|
362
275
|
* unable to to decode a buffer as utf-16-le.
|
|
363
276
|
"""
|
|
364
277
|
peeked_tag = self.PeekTag()
|
|
365
|
-
if peeked_tag == definitions.
|
|
366
|
-
raise errors.ParserError(
|
|
278
|
+
if peeked_tag == definitions.TERMINATOR_TAG:
|
|
279
|
+
raise errors.ParserError("Unexpected TerminatorTag found")
|
|
367
280
|
|
|
368
|
-
if peeked_tag == definitions.
|
|
281
|
+
if peeked_tag == definitions.STRING_POOL_TAG:
|
|
369
282
|
_ = self.decoder.DecodeUint32()
|
|
370
|
-
if len(self.constant_pool) <=
|
|
283
|
+
if len(self.constant_pool) <= 0xFF:
|
|
371
284
|
_, cp_index = self.decoder.DecodeUint8()
|
|
372
|
-
elif len(self.constant_pool) <=
|
|
285
|
+
elif len(self.constant_pool) <= 0xFFFF:
|
|
373
286
|
_, cp_index = self.decoder.DecodeUint16()
|
|
374
|
-
elif len(self.constant_pool) <=
|
|
287
|
+
elif len(self.constant_pool) <= 0xFFFFFFFF:
|
|
375
288
|
_, cp_index = self.decoder.DecodeUint32()
|
|
376
289
|
else:
|
|
377
|
-
raise errors.ParserError(
|
|
290
|
+
raise errors.ParserError("Unexpected constant pool size value.")
|
|
378
291
|
return self.constant_pool[cp_index]
|
|
379
292
|
|
|
380
293
|
_, length_with_8bit_flag = self.decoder.DecodeUint32()
|
|
381
|
-
if length_with_8bit_flag == definitions.
|
|
382
|
-
raise errors.ParserError(
|
|
294
|
+
if length_with_8bit_flag == definitions.TERMINATOR_TAG:
|
|
295
|
+
raise errors.ParserError("Disallowed string length found.")
|
|
383
296
|
|
|
384
297
|
length = length_with_8bit_flag & 0x7FFFFFFF
|
|
385
|
-
is_8bit = length_with_8bit_flag & definitions.
|
|
298
|
+
is_8bit = length_with_8bit_flag & definitions.STRING_DATA_IS_8BIT_FLAG
|
|
386
299
|
|
|
387
300
|
if is_8bit:
|
|
388
301
|
_, characters = self.decoder.ReadBytes(length)
|
|
389
|
-
value = characters.decode(
|
|
302
|
+
value = characters.decode("latin-1")
|
|
390
303
|
else:
|
|
391
|
-
_, characters = self.decoder.ReadBytes(2*length)
|
|
304
|
+
_, characters = self.decoder.ReadBytes(2 * length)
|
|
392
305
|
try:
|
|
393
|
-
value = characters.decode(
|
|
394
|
-
except UnicodeDecodeError:
|
|
306
|
+
value = characters.decode("utf-16-le")
|
|
307
|
+
except UnicodeDecodeError as exc:
|
|
395
308
|
raise errors.ParserError(
|
|
396
|
-
f
|
|
309
|
+
f"Unable to decode {len(characters)} characters as utf-16-le"
|
|
310
|
+
) from exc
|
|
397
311
|
self.constant_pool.append(value)
|
|
398
312
|
return value
|
|
399
313
|
|
|
400
314
|
def DecodeDate(self) -> datetime:
|
|
401
315
|
"""Decodes a Date value."""
|
|
402
316
|
_, timestamp = self.decoder.DecodeDouble()
|
|
403
|
-
value = datetime.utcfromtimestamp(timestamp/1000)
|
|
317
|
+
value = datetime.utcfromtimestamp(timestamp / 1000)
|
|
404
318
|
return value
|
|
405
319
|
|
|
406
320
|
def DecodeFileData(self) -> FileData:
|
|
@@ -416,7 +330,8 @@ class SerializedScriptValueDecoder():
|
|
|
416
330
|
url=url,
|
|
417
331
|
type=file_type,
|
|
418
332
|
name=name,
|
|
419
|
-
last_modified=last_modified
|
|
333
|
+
last_modified=last_modified,
|
|
334
|
+
)
|
|
420
335
|
|
|
421
336
|
def DecodeFileList(self) -> FileList:
|
|
422
337
|
"""Decodes a FileList value."""
|
|
@@ -440,11 +355,11 @@ class SerializedScriptValueDecoder():
|
|
|
440
355
|
|
|
441
356
|
# TODO: make this a dataclass?
|
|
442
357
|
return {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
358
|
+
"width": width,
|
|
359
|
+
"height": height,
|
|
360
|
+
"length": length,
|
|
361
|
+
"data": data,
|
|
362
|
+
"color_space": color_space,
|
|
448
363
|
}
|
|
449
364
|
|
|
450
365
|
def DecodeBlob(self) -> Dict[str, Any]:
|
|
@@ -459,22 +374,24 @@ class SerializedScriptValueDecoder():
|
|
|
459
374
|
|
|
460
375
|
# TODO: make this a dataclass?
|
|
461
376
|
return {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
377
|
+
"url": url,
|
|
378
|
+
"blob_type": blob_type,
|
|
379
|
+
"size": size,
|
|
380
|
+
"memory_cost": memory_cost,
|
|
466
381
|
}
|
|
467
382
|
|
|
468
|
-
def DecodeRegExp(self) -> RegExp:
|
|
383
|
+
def DecodeRegExp(self) -> types.RegExp:
|
|
469
384
|
"""Decodes a RegExp value."""
|
|
470
385
|
pattern = self.DecodeStringData()
|
|
471
386
|
flags = self.DecodeStringData()
|
|
472
|
-
return RegExp(pattern=pattern, flags=flags)
|
|
387
|
+
return types.RegExp(pattern=pattern, flags=flags)
|
|
473
388
|
|
|
474
|
-
def DecodeMapData(self) -> dict:
|
|
389
|
+
def DecodeMapData(self) -> dict[str, Any]:
|
|
475
390
|
"""Decodes a Map value."""
|
|
476
391
|
tag = self.PeekSerializationTag()
|
|
477
|
-
js_map
|
|
392
|
+
js_map: dict[str, Any] = (
|
|
393
|
+
{}
|
|
394
|
+
) # TODO: make this into a JSMap (like JSArray/JSSet)
|
|
478
395
|
self.object_pool.append(js_map)
|
|
479
396
|
|
|
480
397
|
while tag != definitions.SerializationTag.NON_MAP_PROPERTIES:
|
|
@@ -487,41 +404,41 @@ class SerializedScriptValueDecoder():
|
|
|
487
404
|
_, tag = self.DecodeSerializationTag()
|
|
488
405
|
|
|
489
406
|
pool_tag = self.PeekTag()
|
|
490
|
-
while pool_tag != definitions.
|
|
407
|
+
while pool_tag != definitions.TERMINATOR_TAG:
|
|
491
408
|
name = self.DecodeStringData()
|
|
492
409
|
value = self.DecodeValue()
|
|
493
410
|
js_map[name] = value
|
|
494
411
|
pool_tag = self.PeekTag()
|
|
495
412
|
|
|
496
|
-
_,
|
|
413
|
+
_, _ = self.decoder.DecodeUint32()
|
|
497
414
|
return js_map
|
|
498
415
|
|
|
499
|
-
def DecodeSetData(self) -> JSSet:
|
|
416
|
+
def DecodeSetData(self) -> types.JSSet:
|
|
500
417
|
"""Decodes a SetData value."""
|
|
501
418
|
tag = self.PeekSerializationTag()
|
|
502
|
-
js_set = JSSet()
|
|
419
|
+
js_set = types.JSSet()
|
|
503
420
|
self.object_pool.append(js_set)
|
|
504
421
|
|
|
505
422
|
while tag != definitions.SerializationTag.NON_SET_PROPERTIES:
|
|
506
423
|
_, key = self.DecodeValue()
|
|
507
|
-
js_set.
|
|
424
|
+
js_set.values.add(key)
|
|
508
425
|
tag = self.PeekSerializationTag()
|
|
509
426
|
|
|
510
427
|
# consume the NonSetPropertiesTag
|
|
511
428
|
_, tag = self.DecodeSerializationTag()
|
|
512
429
|
|
|
513
430
|
pool_tag = self.PeekTag()
|
|
514
|
-
while pool_tag != definitions.
|
|
431
|
+
while pool_tag != definitions.TERMINATOR_TAG:
|
|
515
432
|
name = self.DecodeStringData()
|
|
516
433
|
value = self.DecodeValue()
|
|
517
434
|
js_set.properties[name] = value
|
|
518
|
-
pool_tag = self.
|
|
435
|
+
pool_tag = self.PeekTag()
|
|
519
436
|
|
|
520
437
|
# consume the TerminatorTag
|
|
521
|
-
_,
|
|
438
|
+
_, _ = self.decoder.DecodeUint32()
|
|
522
439
|
return js_set
|
|
523
440
|
|
|
524
|
-
def DecodeCryptoKey(self) ->
|
|
441
|
+
def DecodeCryptoKey(self) -> Any:
|
|
525
442
|
"""Decodes a CryptoKey value."""
|
|
526
443
|
_, wrapped_key_length = self.decoder.DecodeUint32()
|
|
527
444
|
_, wrapped_key = self.decoder.ReadBytes(wrapped_key_length)
|
|
@@ -532,11 +449,11 @@ class SerializedScriptValueDecoder():
|
|
|
532
449
|
"""Decodes a BigIntData value."""
|
|
533
450
|
_, sign = self.decoder.DecodeUint8()
|
|
534
451
|
_, number_of_elements = self.decoder.DecodeUint32()
|
|
535
|
-
contents =
|
|
452
|
+
contents = bytearray()
|
|
536
453
|
for _ in range(number_of_elements):
|
|
537
454
|
_, element = self.decoder.ReadBytes(8)
|
|
538
455
|
contents.extend(element)
|
|
539
|
-
value = int.from_bytes(contents, byteorder=
|
|
456
|
+
value = int.from_bytes(contents, byteorder="little", signed=bool(sign))
|
|
540
457
|
return value
|
|
541
458
|
|
|
542
459
|
def DecodeArrayBuffer(self) -> bytes:
|
|
@@ -585,24 +502,28 @@ class SerializedScriptValueDecoder():
|
|
|
585
502
|
"""
|
|
586
503
|
_, array_buffer_view_subtag = self.decoder.DecodeUint8()
|
|
587
504
|
array_buffer_view_subtag = definitions.ArrayBufferViewSubtag(
|
|
588
|
-
array_buffer_view_subtag
|
|
505
|
+
array_buffer_view_subtag
|
|
506
|
+
)
|
|
589
507
|
_, byte_offset = self.decoder.DecodeUint64()
|
|
590
508
|
_, byte_length = self.decoder.DecodeUint64()
|
|
591
509
|
_, next_serialization_tag = self.DecodeSerializationTag()
|
|
592
510
|
|
|
593
511
|
if next_serialization_tag == definitions.SerializationTag.ARRAY_BUFFER:
|
|
594
512
|
value = self.DecodeArrayBuffer()
|
|
595
|
-
elif (
|
|
596
|
-
|
|
513
|
+
elif (
|
|
514
|
+
next_serialization_tag == definitions.SerializationTag.OBJECT_REFERENCE
|
|
515
|
+
):
|
|
597
516
|
value = self.DecodeObjectReference()
|
|
598
517
|
else:
|
|
599
518
|
raise errors.ParserError(
|
|
600
|
-
f
|
|
519
|
+
f"Unexpected serialization tag {next_serialization_tag}."
|
|
520
|
+
)
|
|
601
521
|
return ArrayBufferView(
|
|
602
522
|
array_buffer_view_subtag=array_buffer_view_subtag,
|
|
603
523
|
buffer=value,
|
|
604
524
|
offset=byte_offset,
|
|
605
|
-
length=byte_length
|
|
525
|
+
length=byte_length,
|
|
526
|
+
)
|
|
606
527
|
|
|
607
528
|
def DecodeSerializedValue(self) -> Any:
|
|
608
529
|
"""Decodes a serialized value.
|
|
@@ -614,9 +535,10 @@ class SerializedScriptValueDecoder():
|
|
|
614
535
|
ParserError when CurrentVersion is not found.
|
|
615
536
|
"""
|
|
616
537
|
_, current_version = self.decoder.DecodeUint32()
|
|
617
|
-
if current_version != definitions.
|
|
538
|
+
if current_version != definitions.CURRENT_VERSION:
|
|
618
539
|
raise errors.ParserError(
|
|
619
|
-
f
|
|
540
|
+
f"{current_version} is not the expected CurrentVersion"
|
|
541
|
+
)
|
|
620
542
|
_, value = self.DecodeValue()
|
|
621
543
|
return value
|
|
622
544
|
|
|
@@ -629,15 +551,16 @@ class SerializedScriptValueDecoder():
|
|
|
629
551
|
Raises:
|
|
630
552
|
ParserError when an unhandled SerializationTag is found.
|
|
631
553
|
"""
|
|
554
|
+
value: Any = None
|
|
632
555
|
offset, tag = self.DecodeSerializationTag()
|
|
633
556
|
if tag == definitions.SerializationTag.ARRAY:
|
|
634
557
|
value = self.DecodeArray()
|
|
635
558
|
elif tag == definitions.SerializationTag.OBJECT:
|
|
636
559
|
value = self.DecodeObject()
|
|
637
560
|
elif tag == definitions.SerializationTag.UNDEFINED:
|
|
638
|
-
value = Undefined()
|
|
561
|
+
value = types.Undefined()
|
|
639
562
|
elif tag == definitions.SerializationTag.NULL:
|
|
640
|
-
value = Null()
|
|
563
|
+
value = types.Null()
|
|
641
564
|
elif tag == definitions.SerializationTag.INT:
|
|
642
565
|
_, value = self.decoder.DecodeInt32()
|
|
643
566
|
elif tag == definitions.SerializationTag.ZERO:
|
|
@@ -663,7 +586,7 @@ class SerializedScriptValueDecoder():
|
|
|
663
586
|
elif tag == definitions.SerializationTag.STRING:
|
|
664
587
|
value = self.DecodeStringData()
|
|
665
588
|
elif tag == definitions.SerializationTag.EMPTY_STRING:
|
|
666
|
-
value =
|
|
589
|
+
value = ""
|
|
667
590
|
elif tag == definitions.SerializationTag.REG_EXP:
|
|
668
591
|
value = self.DecodeRegExp()
|
|
669
592
|
elif tag == definitions.SerializationTag.OBJECT_REFERENCE:
|
|
@@ -685,7 +608,7 @@ class SerializedScriptValueDecoder():
|
|
|
685
608
|
value = self.DecodeStringData()
|
|
686
609
|
self.object_pool.append(value)
|
|
687
610
|
elif tag == definitions.SerializationTag.EMPTY_STRING_OBJECT:
|
|
688
|
-
value =
|
|
611
|
+
value = ""
|
|
689
612
|
self.object_pool.append(value)
|
|
690
613
|
elif tag == definitions.SerializationTag.NUMBER_OBJECT:
|
|
691
614
|
_, value = self.decoder.DecodeDouble()
|
|
@@ -704,7 +627,7 @@ class SerializedScriptValueDecoder():
|
|
|
704
627
|
value = self.DecodeBigIntData()
|
|
705
628
|
self.object_pool.append(value)
|
|
706
629
|
else:
|
|
707
|
-
raise errors.ParserError(f
|
|
630
|
+
raise errors.ParserError(f"Unhandled Serialization Tag {tag.name} found.")
|
|
708
631
|
return offset, value
|
|
709
632
|
|
|
710
633
|
@classmethod
|
dfindexeddb/indexeddb/types.py
CHANGED
|
@@ -30,6 +30,7 @@ class JSArray:
|
|
|
30
30
|
values: the array values.
|
|
31
31
|
properties: the array properties.
|
|
32
32
|
"""
|
|
33
|
+
|
|
33
34
|
values: List[Any] = dataclasses.field(default_factory=list)
|
|
34
35
|
properties: Dict[Any, Any] = dataclasses.field(default_factory=dict)
|
|
35
36
|
|
|
@@ -45,6 +46,7 @@ class JSSet:
|
|
|
45
46
|
values: the set values.
|
|
46
47
|
properties: the set properties.
|
|
47
48
|
"""
|
|
49
|
+
|
|
48
50
|
values: Set[Any] = dataclasses.field(default_factory=set)
|
|
49
51
|
properties: Dict[Any, Any] = dataclasses.field(default_factory=dict)
|
|
50
52
|
|
|
@@ -57,13 +59,14 @@ class Null:
|
|
|
57
59
|
@dataclasses.dataclass
|
|
58
60
|
class RegExp:
|
|
59
61
|
"""A parsed JavaScript RegExp.
|
|
60
|
-
|
|
62
|
+
|
|
61
63
|
Attributes:
|
|
62
64
|
pattern: the pattern.
|
|
63
65
|
flags: the flags.
|
|
64
66
|
"""
|
|
67
|
+
|
|
65
68
|
pattern: str
|
|
66
|
-
flags:
|
|
69
|
+
flags: str
|
|
67
70
|
|
|
68
71
|
|
|
69
72
|
@dataclasses.dataclass
|