dissect.ole 3.9.dev3__tar.gz → 3.10.dev1__tar.gz
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.
- {dissect_ole-3.9.dev3/dissect.ole.egg-info → dissect_ole-3.10.dev1}/PKG-INFO +2 -2
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/dissect/ole/c_ole.py +3 -1
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/dissect/ole/ole.py +44 -40
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1/dissect.ole.egg-info}/PKG-INFO +2 -2
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/pyproject.toml +48 -5
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/tox.ini +5 -18
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/COPYRIGHT +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/LICENSE +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/MANIFEST.in +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/README.md +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/dissect/ole/__init__.py +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/dissect/ole/exceptions.py +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/dissect.ole.egg-info/SOURCES.txt +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/dissect.ole.egg-info/dependency_links.txt +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/dissect.ole.egg-info/requires.txt +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/dissect.ole.egg-info/top_level.txt +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/setup.cfg +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/tests/docs/Makefile +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/tests/docs/conf.py +0 -0
- {dissect_ole-3.9.dev3 → dissect_ole-3.10.dev1}/tests/docs/index.rst +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: dissect.ole
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.10.dev1
|
|
4
4
|
Summary: A Dissect module implementing a parser for the Object Linking & Embedding (OLE) format, commonly used by document editors on Windows operating systems
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from dissect.cstruct import cstruct
|
|
2
4
|
|
|
3
5
|
ole_def = """
|
|
@@ -34,7 +36,7 @@ struct StructuredStorageHeader { // [offset from start in bytes, length in by
|
|
|
34
36
|
char _abSig[8]; // [000H,08] 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1
|
|
35
37
|
// for current version, was 0x0e, 0x11, 0xfc, 0x0d,
|
|
36
38
|
// 0xd0, 0xcf, 0x11, 0xe0 on old, beta 2 files
|
|
37
|
-
// (late
|
|
39
|
+
// (late '92) which are also supported by the
|
|
38
40
|
// reference implementation
|
|
39
41
|
char _clid[16]; // [008H,16] class id (set with WriteClassStg, retrieved with
|
|
40
42
|
// GetClassFile/ReadClassStg)
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, BinaryIO
|
|
4
|
+
|
|
1
5
|
from dissect.util.stream import AlignedStream
|
|
2
6
|
from dissect.util.ts import wintimestamp
|
|
3
7
|
|
|
4
8
|
from dissect.ole.c_ole import DECOLOR, SIGNATURE, SIGNATURE_BETA, STGTY, c_ole
|
|
5
9
|
from dissect.ole.exceptions import Error, InvalidFileError, NotFoundError
|
|
6
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Iterator
|
|
13
|
+
|
|
7
14
|
|
|
8
15
|
class OLE:
|
|
9
|
-
def __init__(self, fh):
|
|
16
|
+
def __init__(self, fh: BinaryIO):
|
|
10
17
|
self.fh = fh
|
|
11
18
|
self.header = c_ole.StructuredStorageHeader(fh)
|
|
12
19
|
|
|
@@ -37,7 +44,7 @@ class OLE:
|
|
|
37
44
|
self.root = self.directory(0)
|
|
38
45
|
self.ministream = self.root.open()
|
|
39
46
|
|
|
40
|
-
def get(self, path, root=None):
|
|
47
|
+
def get(self, path: str, root: DirectoryEntry | None = None) -> DirectoryEntry:
|
|
41
48
|
root = root or self.root
|
|
42
49
|
|
|
43
50
|
search_path = path.replace("\\", "/")
|
|
@@ -56,7 +63,7 @@ class OLE:
|
|
|
56
63
|
|
|
57
64
|
return node
|
|
58
65
|
|
|
59
|
-
def directory(self, sid):
|
|
66
|
+
def directory(self, sid: int) -> DirectoryEntry:
|
|
60
67
|
try:
|
|
61
68
|
return self._dircache[sid]
|
|
62
69
|
except KeyError:
|
|
@@ -64,7 +71,7 @@ class OLE:
|
|
|
64
71
|
self._dircache[sid] = entry
|
|
65
72
|
return entry
|
|
66
73
|
|
|
67
|
-
def fat(self, sect):
|
|
74
|
+
def fat(self, sect: int) -> int:
|
|
68
75
|
idx, offset = divmod(sect, self.num_fat_entries)
|
|
69
76
|
|
|
70
77
|
try:
|
|
@@ -107,10 +114,10 @@ class OLE:
|
|
|
107
114
|
|
|
108
115
|
return table[offset]
|
|
109
116
|
|
|
110
|
-
def minifat(self, sect):
|
|
117
|
+
def minifat(self, sect: int) -> int:
|
|
111
118
|
return self._minifat[sect]
|
|
112
119
|
|
|
113
|
-
def chain(self, sect, size=None):
|
|
120
|
+
def chain(self, sect: int, size: int | None = None) -> MiniChain:
|
|
114
121
|
try:
|
|
115
122
|
return self._chaincache[sect]
|
|
116
123
|
except KeyError:
|
|
@@ -118,7 +125,7 @@ class OLE:
|
|
|
118
125
|
self._chaincache[sect] = chain
|
|
119
126
|
return chain
|
|
120
127
|
|
|
121
|
-
def minichain(self, sect, size=None):
|
|
128
|
+
def minichain(self, sect: int, size: int | None = None) -> MiniChain:
|
|
122
129
|
try:
|
|
123
130
|
return self._minichaincache[sect]
|
|
124
131
|
except KeyError:
|
|
@@ -128,7 +135,7 @@ class OLE:
|
|
|
128
135
|
|
|
129
136
|
|
|
130
137
|
class DirectoryEntry:
|
|
131
|
-
def __init__(self, ole, sid):
|
|
138
|
+
def __init__(self, ole: OLE, sid: int):
|
|
132
139
|
self.ole = ole
|
|
133
140
|
self.sid = sid
|
|
134
141
|
|
|
@@ -152,20 +159,20 @@ class DirectoryEntry:
|
|
|
152
159
|
|
|
153
160
|
self._dirlist = {}
|
|
154
161
|
|
|
155
|
-
def __repr__(self):
|
|
156
|
-
return "<DirectoryEntry sid={} name={} type={} size=0x{:x}>"
|
|
162
|
+
def __repr__(self) -> str:
|
|
163
|
+
return f"<DirectoryEntry sid={self.sid} name={self.name} type={self.type} size=0x{self.size:x}>"
|
|
157
164
|
|
|
158
|
-
def open(self):
|
|
165
|
+
def open(self) -> ChainStream:
|
|
159
166
|
return self.chain.open()
|
|
160
167
|
|
|
161
|
-
def listdir(self):
|
|
168
|
+
def listdir(self) -> dict[str, DirectoryEntry]:
|
|
162
169
|
if not self._dirlist:
|
|
163
170
|
for entry in self.walk():
|
|
164
171
|
self._dirlist[entry.name] = entry
|
|
165
172
|
|
|
166
173
|
return self._dirlist
|
|
167
174
|
|
|
168
|
-
def walk(self):
|
|
175
|
+
def walk(self) -> Iterator[DirectoryEntry]:
|
|
169
176
|
if self.has_left_sibling:
|
|
170
177
|
yield self.left_sibling
|
|
171
178
|
yield from self.left_sibling.walk()
|
|
@@ -181,77 +188,77 @@ class DirectoryEntry:
|
|
|
181
188
|
yield from self.child.walk()
|
|
182
189
|
|
|
183
190
|
@property
|
|
184
|
-
def child(self):
|
|
191
|
+
def child(self) -> DirectoryEntry | None:
|
|
185
192
|
if not self.has_child:
|
|
186
193
|
return None
|
|
187
194
|
return self.ole.directory(self.entry._sidChild)
|
|
188
195
|
|
|
189
196
|
@property
|
|
190
|
-
def left_sibling(self):
|
|
197
|
+
def left_sibling(self) -> DirectoryEntry | None:
|
|
191
198
|
if not self.has_left_sibling:
|
|
192
199
|
return None
|
|
193
200
|
return self.ole.directory(self.entry._sidLeftSib)
|
|
194
201
|
|
|
195
202
|
@property
|
|
196
|
-
def right_sibling(self):
|
|
203
|
+
def right_sibling(self) -> DirectoryEntry | None:
|
|
197
204
|
if not self.has_right_sibling:
|
|
198
205
|
return None
|
|
199
206
|
return self.ole.directory(self.entry._sidRightSib)
|
|
200
207
|
|
|
201
208
|
@property
|
|
202
|
-
def has_child(self):
|
|
209
|
+
def has_child(self) -> bool:
|
|
203
210
|
return self.entry._sidChild != 0xFFFFFFFF
|
|
204
211
|
|
|
205
212
|
@property
|
|
206
|
-
def has_left_sibling(self):
|
|
213
|
+
def has_left_sibling(self) -> bool:
|
|
207
214
|
return self.entry._sidLeftSib != 0xFFFFFFFF
|
|
208
215
|
|
|
209
216
|
@property
|
|
210
|
-
def has_right_sibling(self):
|
|
217
|
+
def has_right_sibling(self) -> bool:
|
|
211
218
|
return self.entry._sidRightSib != 0xFFFFFFFF
|
|
212
219
|
|
|
213
220
|
@property
|
|
214
|
-
def is_minifat(self):
|
|
221
|
+
def is_minifat(self) -> bool:
|
|
215
222
|
return self.is_stream and self.size < self.ole.mini_cutoff
|
|
216
223
|
|
|
217
224
|
@property
|
|
218
|
-
def is_red(self):
|
|
225
|
+
def is_red(self) -> bool:
|
|
219
226
|
return self.entry._bflags == DECOLOR.DE_RED
|
|
220
227
|
|
|
221
228
|
@property
|
|
222
|
-
def is_black(self):
|
|
229
|
+
def is_black(self) -> bool:
|
|
223
230
|
return self.entry._bflags == DECOLOR.DE_BLACK
|
|
224
231
|
|
|
225
232
|
@property
|
|
226
|
-
def is_valid(self):
|
|
233
|
+
def is_valid(self) -> bool:
|
|
227
234
|
return self.entry._mse == STGTY.STGTY_INVALID
|
|
228
235
|
|
|
229
236
|
@property
|
|
230
|
-
def is_stream(self):
|
|
237
|
+
def is_stream(self) -> bool:
|
|
231
238
|
return self.entry._mse == STGTY.STGTY_STREAM
|
|
232
239
|
|
|
233
240
|
@property
|
|
234
|
-
def is_storage(self):
|
|
241
|
+
def is_storage(self) -> bool:
|
|
235
242
|
return self.entry._mse == STGTY.STGTY_STORAGE
|
|
236
243
|
|
|
237
244
|
|
|
238
245
|
class Chain:
|
|
239
|
-
def __init__(self, ole, sect, size=None):
|
|
246
|
+
def __init__(self, ole: OLE, sect: int, size: int | None = None):
|
|
240
247
|
self.ole = ole
|
|
241
248
|
self.sect = sect
|
|
242
249
|
self.size = size
|
|
243
250
|
self.chain = [sect]
|
|
244
251
|
self.ended = False
|
|
245
252
|
|
|
246
|
-
def __len__(self):
|
|
253
|
+
def __len__(self) -> int:
|
|
247
254
|
self.fill()
|
|
248
255
|
return len(self.chain)
|
|
249
256
|
|
|
250
|
-
def __iter__(self):
|
|
257
|
+
def __iter__(self) -> Iterator[int]:
|
|
251
258
|
self.fill()
|
|
252
259
|
return iter(self.chain)
|
|
253
260
|
|
|
254
|
-
def __getitem__(self, i):
|
|
261
|
+
def __getitem__(self, i: int) -> int:
|
|
255
262
|
cur = len(self.chain)
|
|
256
263
|
tail = self.chain[-1]
|
|
257
264
|
|
|
@@ -271,10 +278,10 @@ class Chain:
|
|
|
271
278
|
|
|
272
279
|
return self.chain[i]
|
|
273
280
|
|
|
274
|
-
def open(self):
|
|
281
|
+
def open(self) -> ChainStream:
|
|
275
282
|
return ChainStream(self.ole.fh, self, self.ole.sector_size, offset=self.ole.sector_size)
|
|
276
283
|
|
|
277
|
-
def fill(self):
|
|
284
|
+
def fill(self) -> None:
|
|
278
285
|
if self.ended:
|
|
279
286
|
return
|
|
280
287
|
|
|
@@ -283,20 +290,20 @@ class Chain:
|
|
|
283
290
|
except IndexError:
|
|
284
291
|
pass
|
|
285
292
|
|
|
286
|
-
def _lookup(self, sect):
|
|
293
|
+
def _lookup(self, sect: int) -> int:
|
|
287
294
|
return self.ole.fat(sect)
|
|
288
295
|
|
|
289
296
|
|
|
290
297
|
class MiniChain(Chain):
|
|
291
|
-
def open(self):
|
|
298
|
+
def open(self) -> ChainStream:
|
|
292
299
|
return ChainStream(self.ole.ministream, self, self.ole.mini_sector_size)
|
|
293
300
|
|
|
294
|
-
def _lookup(self, sect):
|
|
301
|
+
def _lookup(self, sect: int) -> int:
|
|
295
302
|
return self.ole.minifat(sect)
|
|
296
303
|
|
|
297
304
|
|
|
298
305
|
class ChainStream(AlignedStream):
|
|
299
|
-
def __init__(self, stream, chain, sector_size, offset=0):
|
|
306
|
+
def __init__(self, stream: BinaryIO, chain: Chain, sector_size: int, offset: int = 0):
|
|
300
307
|
self._fh = stream
|
|
301
308
|
self.chain = chain
|
|
302
309
|
self.sector_size = sector_size
|
|
@@ -304,7 +311,7 @@ class ChainStream(AlignedStream):
|
|
|
304
311
|
|
|
305
312
|
super().__init__(chain.size)
|
|
306
313
|
|
|
307
|
-
def _read(self, offset, length):
|
|
314
|
+
def _read(self, offset: int, length: int) -> bytes:
|
|
308
315
|
r = []
|
|
309
316
|
|
|
310
317
|
if not self.size and length == -1:
|
|
@@ -321,10 +328,7 @@ class ChainStream(AlignedStream):
|
|
|
321
328
|
except IndexError:
|
|
322
329
|
break
|
|
323
330
|
|
|
324
|
-
if self.size
|
|
325
|
-
sectread = min(self.size - offset, sector_size)
|
|
326
|
-
else:
|
|
327
|
-
sectread = sector_size
|
|
331
|
+
sectread = min(self.size - offset, sector_size) if self.size else sector_size
|
|
328
332
|
fileoffset = self.offset + sectnum * sector_size
|
|
329
333
|
|
|
330
334
|
self._fh.seek(fileoffset)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: dissect.ole
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.10.dev1
|
|
4
4
|
Summary: A Dissect module implementing a parser for the Object Linking & Embedding (OLE) format, commonly used by document editors on Windows operating systems
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
|
@@ -41,13 +41,56 @@ dev = [
|
|
|
41
41
|
"dissect.util>=3.0.dev,<4.0.dev",
|
|
42
42
|
]
|
|
43
43
|
|
|
44
|
-
[tool.
|
|
44
|
+
[tool.ruff]
|
|
45
45
|
line-length = 120
|
|
46
|
+
required-version = ">=0.9.0"
|
|
46
47
|
|
|
47
|
-
[tool.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
[tool.ruff.format]
|
|
49
|
+
docstring-code-format = true
|
|
50
|
+
|
|
51
|
+
[tool.ruff.lint]
|
|
52
|
+
select = [
|
|
53
|
+
"F",
|
|
54
|
+
"E",
|
|
55
|
+
"W",
|
|
56
|
+
"I",
|
|
57
|
+
"UP",
|
|
58
|
+
"YTT",
|
|
59
|
+
"ANN",
|
|
60
|
+
"B",
|
|
61
|
+
"C4",
|
|
62
|
+
"DTZ",
|
|
63
|
+
"T10",
|
|
64
|
+
"FA",
|
|
65
|
+
"ISC",
|
|
66
|
+
"G",
|
|
67
|
+
"INP",
|
|
68
|
+
"PIE",
|
|
69
|
+
"PYI",
|
|
70
|
+
"PT",
|
|
71
|
+
"Q",
|
|
72
|
+
"RSE",
|
|
73
|
+
"RET",
|
|
74
|
+
"SLOT",
|
|
75
|
+
"SIM",
|
|
76
|
+
"TID",
|
|
77
|
+
"TCH",
|
|
78
|
+
"PTH",
|
|
79
|
+
"PLC",
|
|
80
|
+
"TRY",
|
|
81
|
+
"FLY",
|
|
82
|
+
"PERF",
|
|
83
|
+
"FURB",
|
|
84
|
+
"RUF",
|
|
85
|
+
]
|
|
86
|
+
ignore = ["E203", "B904", "UP024", "ANN002", "ANN003", "ANN204", "ANN401", "SIM105", "TRY003"]
|
|
87
|
+
|
|
88
|
+
[tool.ruff.lint.per-file-ignores]
|
|
89
|
+
"tests/docs/**" = ["INP001"]
|
|
90
|
+
|
|
91
|
+
[tool.ruff.lint.isort]
|
|
92
|
+
known-first-party = ["dissect.ole"]
|
|
93
|
+
known-third-party = ["dissect"]
|
|
51
94
|
|
|
52
95
|
[tool.setuptools]
|
|
53
96
|
license-files = ["LICENSE", "COPYRIGHT"]
|
|
@@ -32,31 +32,18 @@ commands =
|
|
|
32
32
|
[testenv:fix]
|
|
33
33
|
package = skip
|
|
34
34
|
deps =
|
|
35
|
-
|
|
36
|
-
isort==5.11.4
|
|
35
|
+
ruff==0.9.2
|
|
37
36
|
commands =
|
|
38
|
-
|
|
39
|
-
isort dissect
|
|
37
|
+
ruff format dissect tests
|
|
40
38
|
|
|
41
39
|
[testenv:lint]
|
|
42
40
|
package = skip
|
|
43
41
|
deps =
|
|
44
|
-
|
|
45
|
-
flake8
|
|
46
|
-
flake8-black
|
|
47
|
-
flake8-isort
|
|
48
|
-
isort==5.11.4
|
|
42
|
+
ruff==0.9.2
|
|
49
43
|
vermin
|
|
50
44
|
commands =
|
|
51
|
-
|
|
52
|
-
vermin -t=3.9- --no-tips --lint dissect
|
|
53
|
-
|
|
54
|
-
[flake8]
|
|
55
|
-
max-line-length = 120
|
|
56
|
-
extend-ignore =
|
|
57
|
-
# See https://github.com/PyCQA/pycodestyle/issues/373
|
|
58
|
-
E203,
|
|
59
|
-
statistics = True
|
|
45
|
+
ruff check dissect tests
|
|
46
|
+
vermin -t=3.9- --no-tips --lint dissect tests
|
|
60
47
|
|
|
61
48
|
[testenv:docs-build]
|
|
62
49
|
allowlist_externals = make
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|