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
dfindexeddb/utils.py
CHANGED
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
"""Utilities for dfindexeddb."""
|
|
16
16
|
from __future__ import annotations
|
|
17
|
+
|
|
17
18
|
import copy
|
|
18
19
|
import dataclasses
|
|
19
20
|
import io
|
|
20
21
|
import os
|
|
21
22
|
import struct
|
|
22
|
-
from typing import BinaryIO, Tuple, Type, TypeVar
|
|
23
|
-
|
|
23
|
+
from typing import Any, BinaryIO, Literal, Tuple, Type, TypeVar
|
|
24
24
|
|
|
25
25
|
from dfindexeddb import errors
|
|
26
26
|
|
|
@@ -28,8 +28,8 @@ from dfindexeddb import errors
|
|
|
28
28
|
class StreamDecoder:
|
|
29
29
|
"""A helper class to decode primitive data types from BinaryIO streams.
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
Attributes:
|
|
32
|
+
stream (BinaryIO): the binary stream.
|
|
33
33
|
"""
|
|
34
34
|
|
|
35
35
|
def __init__(self, stream: BinaryIO):
|
|
@@ -51,7 +51,7 @@ class StreamDecoder:
|
|
|
51
51
|
self.stream.seek(current_offset, os.SEEK_SET)
|
|
52
52
|
num_rem_bytes = end_offset - current_offset
|
|
53
53
|
if num_rem_bytes < 0:
|
|
54
|
-
raise errors.DecoderError(
|
|
54
|
+
raise errors.DecoderError("Negative number of remaining bytes.")
|
|
55
55
|
return num_rem_bytes
|
|
56
56
|
|
|
57
57
|
def ReadBytes(self, count: int = -1) -> Tuple[int, bytes]:
|
|
@@ -71,10 +71,11 @@ class StreamDecoder:
|
|
|
71
71
|
offset = self.stream.tell()
|
|
72
72
|
buffer = self.stream.read(count)
|
|
73
73
|
if count == -1 and not buffer:
|
|
74
|
-
raise errors.DecoderError(f
|
|
74
|
+
raise errors.DecoderError(f"No bytes available at offset {offset}")
|
|
75
75
|
if count != -1 and len(buffer) != count:
|
|
76
76
|
raise errors.DecoderError(
|
|
77
|
-
f
|
|
77
|
+
f"Read {len(buffer)} bytes, but wanted {count} at offset {offset}"
|
|
78
|
+
)
|
|
78
79
|
return offset, buffer
|
|
79
80
|
|
|
80
81
|
def PeekBytes(self, count: int) -> Tuple[int, bytes]:
|
|
@@ -94,8 +95,8 @@ class StreamDecoder:
|
|
|
94
95
|
def DecodeInt(
|
|
95
96
|
self,
|
|
96
97
|
byte_count: int = -1,
|
|
97
|
-
byte_order:
|
|
98
|
-
signed: bool = True
|
|
98
|
+
byte_order: Literal["big", "little"] = "little",
|
|
99
|
+
signed: bool = True,
|
|
99
100
|
) -> Tuple[int, int]:
|
|
100
101
|
"""Decodes an integer from the binary stream.
|
|
101
102
|
|
|
@@ -162,27 +163,27 @@ class StreamDecoder:
|
|
|
162
163
|
"""Returns a Tuple of the offset and a double-precision float."""
|
|
163
164
|
offset, blob = self.ReadBytes(8)
|
|
164
165
|
if little_endian:
|
|
165
|
-
value = struct.unpack(
|
|
166
|
+
value = struct.unpack("<d", blob)[0]
|
|
166
167
|
else:
|
|
167
|
-
value = struct.unpack(
|
|
168
|
+
value = struct.unpack(">d", blob)[0]
|
|
168
169
|
return offset, value
|
|
169
170
|
|
|
170
171
|
def DecodeFloat(self, little_endian: bool = True) -> Tuple[int, float]:
|
|
171
172
|
"""Returns a Tuple of the offset and a single-precision float."""
|
|
172
173
|
offset, blob = self.ReadBytes(4)
|
|
173
174
|
if little_endian:
|
|
174
|
-
value = struct.unpack(
|
|
175
|
+
value = struct.unpack("<f", blob)[0]
|
|
175
176
|
else:
|
|
176
|
-
value = struct.unpack(
|
|
177
|
+
value = struct.unpack(">f", blob)[0]
|
|
177
178
|
return offset, value
|
|
178
179
|
|
|
179
180
|
def DecodeVarint(self, max_bytes: int = 10) -> Tuple[int, int]:
|
|
180
181
|
"""Returns a Tuple of the offset and the decoded base128 varint."""
|
|
181
182
|
offset = self.stream.tell()
|
|
182
183
|
varint = 0
|
|
183
|
-
for i in range(0, max_bytes*7, 7):
|
|
184
|
+
for i in range(0, max_bytes * 7, 7):
|
|
184
185
|
_, varint_part = self.ReadBytes(1)
|
|
185
|
-
varint |= (varint_part[0] &
|
|
186
|
+
varint |= (varint_part[0] & 0x7F) << i
|
|
186
187
|
if not varint_part[0] >> 7:
|
|
187
188
|
break
|
|
188
189
|
return offset, varint
|
|
@@ -209,7 +210,7 @@ class StreamDecoder:
|
|
|
209
210
|
return self.DecodeZigzagVarint(max_bytes=10)
|
|
210
211
|
|
|
211
212
|
|
|
212
|
-
T = TypeVar(
|
|
213
|
+
T = TypeVar("T")
|
|
213
214
|
|
|
214
215
|
|
|
215
216
|
class FromDecoderMixin:
|
|
@@ -217,7 +218,8 @@ class FromDecoderMixin:
|
|
|
217
218
|
|
|
218
219
|
@classmethod
|
|
219
220
|
def FromDecoder(
|
|
220
|
-
cls: Type[T], decoder: StreamDecoder, base_offset: int = 0
|
|
221
|
+
cls: Type[T], decoder: StreamDecoder, base_offset: int = 0
|
|
222
|
+
) -> T:
|
|
221
223
|
"""Decodes a class type from the current position of a StreamDecoder.
|
|
222
224
|
|
|
223
225
|
Args:
|
|
@@ -233,8 +235,7 @@ class FromDecoderMixin:
|
|
|
233
235
|
raise NotImplementedError
|
|
234
236
|
|
|
235
237
|
@classmethod
|
|
236
|
-
def FromStream(
|
|
237
|
-
cls: Type[T], stream: BinaryIO, base_offset: int = 0) -> T:
|
|
238
|
+
def FromStream(cls: Type[T], stream: BinaryIO, base_offset: int = 0) -> T:
|
|
238
239
|
"""Decodes a class type from the current position of a binary stream.
|
|
239
240
|
|
|
240
241
|
Args:
|
|
@@ -245,11 +246,12 @@ class FromDecoderMixin:
|
|
|
245
246
|
The class instance.
|
|
246
247
|
"""
|
|
247
248
|
decoder = StreamDecoder(stream)
|
|
248
|
-
return cls.FromDecoder(
|
|
249
|
+
return cls.FromDecoder( # type: ignore[attr-defined,no-any-return]
|
|
250
|
+
decoder=decoder, base_offset=base_offset
|
|
251
|
+
)
|
|
249
252
|
|
|
250
253
|
@classmethod
|
|
251
|
-
def FromBytes(
|
|
252
|
-
cls: Type[T], raw_data: bytes, base_offset: int = 0) -> T:
|
|
254
|
+
def FromBytes(cls: Type[T], raw_data: bytes, base_offset: int = 0) -> T:
|
|
253
255
|
"""Parses a class type from raw bytes.
|
|
254
256
|
|
|
255
257
|
Args:
|
|
@@ -260,10 +262,12 @@ class FromDecoderMixin:
|
|
|
260
262
|
The class instance.
|
|
261
263
|
"""
|
|
262
264
|
stream = io.BytesIO(raw_data)
|
|
263
|
-
return cls.FromStream(
|
|
265
|
+
return cls.FromStream( # type: ignore[attr-defined,no-any-return]
|
|
266
|
+
stream=stream, base_offset=base_offset
|
|
267
|
+
)
|
|
264
268
|
|
|
265
269
|
|
|
266
|
-
def asdict(obj, *, dict_factory=dict): # pylint: disable=invalid-name
|
|
270
|
+
def asdict(obj, *, dict_factory=dict) -> Any: # type: ignore[no-untyped-def] # pylint: disable=invalid-name
|
|
267
271
|
"""Custom implementation of the asdict dataclasses method to include the
|
|
268
272
|
class name under the __type__ attribute name.
|
|
269
273
|
"""
|
|
@@ -272,24 +276,25 @@ def asdict(obj, *, dict_factory=dict): # pylint: disable=invalid-name
|
|
|
272
276
|
return _asdict_inner(obj, dict_factory)
|
|
273
277
|
|
|
274
278
|
|
|
275
|
-
def _asdict_inner(obj, dict_factory):
|
|
279
|
+
def _asdict_inner(obj, dict_factory): # type: ignore[no-untyped-def]
|
|
276
280
|
"""Custom implementation of the _asdict_inner dataclasses method."""
|
|
277
281
|
if dataclasses.is_dataclass(obj):
|
|
278
|
-
result = [(
|
|
282
|
+
result = [("__type__", obj.__class__.__name__)]
|
|
279
283
|
for f in dataclasses.fields(obj):
|
|
280
284
|
value = _asdict_inner(getattr(obj, f.name), dict_factory)
|
|
281
285
|
result.append((f.name, value))
|
|
282
286
|
return dict_factory(result)
|
|
283
287
|
|
|
284
|
-
if isinstance(obj, tuple) and hasattr(obj,
|
|
288
|
+
if isinstance(obj, tuple) and hasattr(obj, "_fields"):
|
|
285
289
|
return type(obj)(*[_asdict_inner(v, dict_factory) for v in obj])
|
|
286
290
|
|
|
287
291
|
if isinstance(obj, (list, tuple)):
|
|
288
292
|
return type(obj)(_asdict_inner(v, dict_factory) for v in obj)
|
|
289
293
|
|
|
290
294
|
if isinstance(obj, dict):
|
|
291
|
-
return type(obj)(
|
|
292
|
-
|
|
293
|
-
|
|
295
|
+
return type(obj)(
|
|
296
|
+
(_asdict_inner(k, dict_factory), _asdict_inner(v, dict_factory))
|
|
297
|
+
for k, v in obj.items()
|
|
298
|
+
)
|
|
294
299
|
|
|
295
300
|
return copy.deepcopy(obj)
|
dfindexeddb/version.py
CHANGED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dfindexeddb
|
|
3
|
+
Version: 20251109
|
|
4
|
+
Summary: dfindexeddb is an experimental Python tool for performing digital forensic analysis of IndexedDB and leveldb files.
|
|
5
|
+
Author-email: Syd Pleno <sydp@google.com>
|
|
6
|
+
Maintainer-email: dfIndexeddb Developers <dfindexeddb-dev@googlegroups.com>
|
|
7
|
+
License-Expression: Apache-2.0
|
|
8
|
+
Project-URL: Homepage, https://github.com/google/dfindexeddb
|
|
9
|
+
Project-URL: Documentation, https://github.com/google/dfindexeddb/tree/main/docs
|
|
10
|
+
Project-URL: Repository, https://github.com/google/dfindexeddb
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/google/dfindexeddb/issues
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: python-snappy==0.6.1
|
|
18
|
+
Requires-Dist: zstd==1.5.5.1
|
|
19
|
+
Provides-Extra: plugins
|
|
20
|
+
Requires-Dist: protobuf; extra == "plugins"
|
|
21
|
+
Requires-Dist: dfdatetime; extra == "plugins"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# dfIndexeddb
|
|
25
|
+
|
|
26
|
+
dfindexeddb is an experimental Python tool for performing digital forensic
|
|
27
|
+
analysis of IndexedDB and LevelDB files.
|
|
28
|
+
|
|
29
|
+
It parses LevelDB, IndexedDB and JavaScript structures from these files without
|
|
30
|
+
requiring native libraries. (Note: only a subset of IndexedDB key types and
|
|
31
|
+
JavaScript types for Firefox, Safari and Chromium-based browsers are currently supported).
|
|
32
|
+
|
|
33
|
+
The content of IndexedDB files is dependent on what a web application stores
|
|
34
|
+
locally/offline using the web browser's
|
|
35
|
+
[IndexedDB API](https://www.w3.org/TR/IndexedDB/). Examples of content might
|
|
36
|
+
include:
|
|
37
|
+
* text from a text/source-code editor application,
|
|
38
|
+
* emails and contact information from an e-mail application,
|
|
39
|
+
* images and metadata from a photo gallery application
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
1. [Linux] Install the snappy compression development package
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
$ sudo apt install libsnappy-dev
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
2. Create a virtual environment and install the package
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
$ python3 -m venv .venv
|
|
54
|
+
$ source .venv/bin/activate
|
|
55
|
+
$ pip install dfindexeddb
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
To also install the dependencies for leveldb/indexeddb plugins, run
|
|
59
|
+
```
|
|
60
|
+
$ pip install 'dfindexeddb[plugins]'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Installation from source
|
|
65
|
+
|
|
66
|
+
1. [Linux] Install the snappy compression development package
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
$ sudo apt install libsnappy-dev
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
2. Clone or download/unzip the repository to your local machine.
|
|
73
|
+
|
|
74
|
+
3. Create a virtual environment and install the package
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
$ python3 -m venv .venv
|
|
78
|
+
$ source .venv/bin/activate
|
|
79
|
+
$ pip install .
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
To also install the dependencies for leveldb/indexeddb plugins, run
|
|
83
|
+
```
|
|
84
|
+
$ pip install '.[plugins]'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Usage
|
|
88
|
+
|
|
89
|
+
Two CLI tools for parsing IndexedDB/LevelDB files are available after
|
|
90
|
+
installation:
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
### IndexedDB
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
$ dfindexeddb -h
|
|
97
|
+
usage: dfindexeddb [-h] {db,ldb,log} ...
|
|
98
|
+
|
|
99
|
+
A cli tool for parsing indexeddb files
|
|
100
|
+
|
|
101
|
+
positional arguments:
|
|
102
|
+
{db,ldb,log}
|
|
103
|
+
db Parse a directory as indexeddb.
|
|
104
|
+
ldb Parse a ldb file as indexeddb.
|
|
105
|
+
log Parse a log file as indexeddb.
|
|
106
|
+
|
|
107
|
+
options:
|
|
108
|
+
-h, --help show this help message and exit
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Examples:
|
|
112
|
+
|
|
113
|
+
To parse IndexedDB records from an sqlite file for Firefox and output the
|
|
114
|
+
results as JSON, use the following command:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
dfindexeddb db -s SOURCE --format firefox -o json
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
To parse IndexedDB records from an sqlite file for Safari and output the
|
|
121
|
+
results as JSON-L, use the following command:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
dfindexeddb db -s SOURCE --format safari -o jsonl
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
To parse IndexedDB records from a LevelDB folder for Chrome/Chromium, using the
|
|
128
|
+
manifest file to determine recovered records and output as JSON, use the
|
|
129
|
+
following command:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
dfindexeddb db -s SOURCE --format chrome --use_manifest
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
To parse IndexedDB records from a LevelDB ldb (.ldb) file and output the
|
|
136
|
+
results as JSON-L, use the following command:
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
dfindexeddb ldb -s SOURCE -o jsonl
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
To parse IndexedDB records from a LevelDB log (.log) file and output the
|
|
143
|
+
results as the Python printable representation, use the following command:
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
dfindexeddb log -s SOURCE -o repr
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
To parse a file as a Chrome/Chromium IndexedDB blink value and output the
|
|
150
|
+
results as JSON:
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
dfindexeddb blink -s SOURCE
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### LevelDB
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
$ dfleveldb -h
|
|
160
|
+
usage: dfleveldb [-h] {db,log,ldb,descriptor} ...
|
|
161
|
+
|
|
162
|
+
A cli tool for parsing leveldb files
|
|
163
|
+
|
|
164
|
+
positional arguments:
|
|
165
|
+
{db,log,ldb,descriptor}
|
|
166
|
+
db Parse a directory as leveldb.
|
|
167
|
+
log Parse a leveldb log file.
|
|
168
|
+
ldb Parse a leveldb table (.ldb) file.
|
|
169
|
+
descriptor Parse a leveldb descriptor (MANIFEST) file.
|
|
170
|
+
|
|
171
|
+
options:
|
|
172
|
+
-h, --help show this help message and exit
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### Examples
|
|
176
|
+
|
|
177
|
+
To parse records from a LevelDB folder, use the following command:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
dfleveldb db -s SOURCE
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
To parse records from a LevelDB folder, and use the sequence number to
|
|
184
|
+
determine recovered records and output as JSON, use the
|
|
185
|
+
following command:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
dfleveldb db -s SOURCE --use_sequence_number
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
To parse blocks / physical records/ write batches / internal key records from a
|
|
192
|
+
LevelDB log (.log) file, use the following command, specifying the type (block,
|
|
193
|
+
physical_records, etc) via the `-t` option. By default, internal key records are parsed:
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
$ dfleveldb log -s SOURCE [-t {blocks,physical_records,write_batches,parsed_internal_key}]
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
To parse blocks / records from a LevelDB table (.ldb) file, use the following
|
|
200
|
+
command, specifying the type (blocks, records) via the `-t` option. By
|
|
201
|
+
default, records are parsed:
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
$ dfleveldb ldb -s SOURCE [-t {blocks,records}]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
To parse version edit records from a Descriptor (MANIFEST) file, use the
|
|
208
|
+
following command:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
$ dfleveldb descriptor -s SOURCE [-o {json,jsonl,repr}] [-t {blocks,physical_records,versionedit} | -v]
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Plugins
|
|
215
|
+
|
|
216
|
+
To apply a plugin parser for a leveldb file/folder, add the
|
|
217
|
+
`--plugin [Plugin Name]` argument. Currently, there is support for the
|
|
218
|
+
following artifacts:
|
|
219
|
+
|
|
220
|
+
| Plugin Name | Artifact Name |
|
|
221
|
+
| -------- | ------- |
|
|
222
|
+
| `ChromeNotificationRecord` | Chrome/Chromium Notifications |
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
dfindexeddb/__init__.py,sha256=KPYL9__l8od6_OyDfGRTgaJ6iy_fqIgZ-dS2S-e3Rac,599
|
|
2
|
+
dfindexeddb/errors.py,sha256=PNpwyf_lrPc4TE77oAakX3mu5D_YcP3f80wq8Y1LkvY,749
|
|
3
|
+
dfindexeddb/utils.py,sha256=gep43m3LpAZNnW6JFOQTDn8MRrEXzGlc1NZ5yMuBsvI,10194
|
|
4
|
+
dfindexeddb/version.py,sha256=C6239PGrB1o3OzfiWQ-W1g11b6xwmAfs53zspL7Ub1w,758
|
|
5
|
+
dfindexeddb/indexeddb/__init__.py,sha256=kExXSVBCTKCD5BZJkdMfUMqGksH-DMJxP2_lI0gq-BE,575
|
|
6
|
+
dfindexeddb/indexeddb/cli.py,sha256=gEVlE6ZRAu360Oc5dePVQEupKLEGQUt6mUljlbptIUE,7686
|
|
7
|
+
dfindexeddb/indexeddb/types.py,sha256=m9llt7PTVMSvhsQ_uDIlZJUkbM_5k3gUx5CtMc3TvC8,1893
|
|
8
|
+
dfindexeddb/indexeddb/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
dfindexeddb/indexeddb/chromium/__init__.py,sha256=kExXSVBCTKCD5BZJkdMfUMqGksH-DMJxP2_lI0gq-BE,575
|
|
10
|
+
dfindexeddb/indexeddb/chromium/blink.py,sha256=oQdbgzn4w1dUs3jAqtCF0078o4ccupHSjH0hB42vJSc,32978
|
|
11
|
+
dfindexeddb/indexeddb/chromium/definitions.py,sha256=cNFUhE9ngd_-NSNnH-0sXNRaX1keNrN6UKvF_ADaYds,8864
|
|
12
|
+
dfindexeddb/indexeddb/chromium/record.py,sha256=AwZTvgjwj3wOPSNh2S94SXD2Ynhi8l1xqTB1asWp3vg,49373
|
|
13
|
+
dfindexeddb/indexeddb/chromium/v8.py,sha256=cbaFQmhZoJMWGphLdvz1ZcvTge9MSh6GLH4K1yQNiWk,21888
|
|
14
|
+
dfindexeddb/indexeddb/firefox/__init__.py,sha256=kExXSVBCTKCD5BZJkdMfUMqGksH-DMJxP2_lI0gq-BE,575
|
|
15
|
+
dfindexeddb/indexeddb/firefox/definitions.py,sha256=C9qziLvNMmWFwVrt6K_lw4I_1YbiWJ9nxb65x0TefvU,4306
|
|
16
|
+
dfindexeddb/indexeddb/firefox/gecko.py,sha256=rcph8PrX0IL_67cCvx9EsbEK_8r8lkXvW-nU7_2IsxA,19932
|
|
17
|
+
dfindexeddb/indexeddb/firefox/record.py,sha256=wm0jHuTK47Qp6NPb2dQzRcqHnFTxOaPIz9sDHqb8gSc,6878
|
|
18
|
+
dfindexeddb/indexeddb/safari/__init__.py,sha256=kExXSVBCTKCD5BZJkdMfUMqGksH-DMJxP2_lI0gq-BE,575
|
|
19
|
+
dfindexeddb/indexeddb/safari/definitions.py,sha256=_st96KuCjgzAeltDGylmoojlCtVvTGQPWwqzYCuX3s8,2793
|
|
20
|
+
dfindexeddb/indexeddb/safari/record.py,sha256=TKD1ltTOzhjKKU-3sCy7zm4H2r4NAZjlNel57m4BDZo,8132
|
|
21
|
+
dfindexeddb/indexeddb/safari/webkit.py,sha256=16Vj7f3Pbts2ebdFg1dXmqQ3ixAKKv4_3znvsP21b4U,20816
|
|
22
|
+
dfindexeddb/leveldb/__init__.py,sha256=KPYL9__l8od6_OyDfGRTgaJ6iy_fqIgZ-dS2S-e3Rac,599
|
|
23
|
+
dfindexeddb/leveldb/cli.py,sha256=7CkM9P0bk83uj1cJrGFai82FIPBF0sul1tI2KUTMokA,10291
|
|
24
|
+
dfindexeddb/leveldb/definitions.py,sha256=cvwO3BkbEh5ISlPzlM_TL2xs-1lRyqepiyy7_ZZ8-_A,1490
|
|
25
|
+
dfindexeddb/leveldb/descriptor.py,sha256=Cmy9y73cBeb586pryoagZ0-Zb2iA_8MCRGu6SN5dKbo,12479
|
|
26
|
+
dfindexeddb/leveldb/ldb.py,sha256=7sjpqMXrU6iXz5d4GAx58BuEknpjPM3qlrzNv6jdLIk,8140
|
|
27
|
+
dfindexeddb/leveldb/log.py,sha256=oCMpLH8STOSK0qM-u44wnf781ehy5-JPe1e_osMlgL4,9510
|
|
28
|
+
dfindexeddb/leveldb/record.py,sha256=Fnz7i446IO3IjJZAlB9olM_VSiEaM2ONHzG7BqrBzak,11978
|
|
29
|
+
dfindexeddb/leveldb/utils.py,sha256=-70BjnttqGHHG1Ze9r8Pxspp6LGbRqHxXb3FODyXF6I,3879
|
|
30
|
+
dfindexeddb/leveldb/plugins/__init__.py,sha256=RoC6tRkq8FhqIaFs6jwu1fao_qaSvlSfIFxQVjWregI,690
|
|
31
|
+
dfindexeddb/leveldb/plugins/chrome_notifications.py,sha256=H2TgriK_mre1kflTh2Zd2aIvcoHXa_qJum5f5Sbwp88,5485
|
|
32
|
+
dfindexeddb/leveldb/plugins/interface.py,sha256=1kFbhzgiRLQ18gdOc-pzbizQ7dp_Li-ut4ZHjXSxKIU,1193
|
|
33
|
+
dfindexeddb/leveldb/plugins/manager.py,sha256=UV8dtdeu6xPCNzvx3fSef1WrZxGPzkPBD8mD2qpoVzY,2317
|
|
34
|
+
dfindexeddb/leveldb/plugins/notification_database_data_pb2.py,sha256=DCPZHbyq2szLgrBprOKrJKycKJma8Z_SnAQM6Jx9bZg,4389
|
|
35
|
+
dfindexeddb-20251109.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
36
|
+
dfindexeddb-20251109.dist-info/METADATA,sha256=pewsavAQMLj0KqCnAxod4ZswNQ02HV9dBXEIEirLiLc,6015
|
|
37
|
+
dfindexeddb-20251109.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
38
|
+
dfindexeddb-20251109.dist-info/entry_points.txt,sha256=WG9YNLZ9lBx4Q9QF6wS4dZdZfADT3Zs4_-MV5TcA0ls,102
|
|
39
|
+
dfindexeddb-20251109.dist-info/top_level.txt,sha256=X9OTaub1c8S_JJ7g-f8JdkhhdiZ4x1j4eni1hdUCwE4,12
|
|
40
|
+
dfindexeddb-20251109.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Names should be added to this file with this pattern:
|
|
2
|
-
#
|
|
3
|
-
# For individuals:
|
|
4
|
-
# Name (email address)
|
|
5
|
-
#
|
|
6
|
-
# For organizations:
|
|
7
|
-
# Organization (fnmatch pattern)
|
|
8
|
-
#
|
|
9
|
-
# See python fnmatch module documentation for more information.
|
|
10
|
-
|
|
11
|
-
Google Inc. (*@google.com)
|
|
12
|
-
Syd Pleno (syd.pleno@gmail.com)
|