dissect.thumbcache 1.9.dev3__tar.gz → 1.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_thumbcache-1.9.dev3/dissect.thumbcache.egg-info → dissect_thumbcache-1.10.dev1}/PKG-INFO +2 -2
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/c_thumbcache.py +4 -2
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/exceptions.py +0 -8
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/index.py +27 -26
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/thumbcache.py +8 -4
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/thumbcache_file.py +25 -24
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/tools/extract_images.py +7 -3
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/tools/extract_with_index.py +8 -3
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/tools/utils.py +8 -4
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/util.py +7 -2
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1/dissect.thumbcache.egg-info}/PKG-INFO +2 -2
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect.thumbcache.egg-info/SOURCES.txt +1 -1
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/pyproject.toml +48 -5
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/test_index.py +9 -8
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/test_thumbcache.py +9 -7
- dissect_thumbcache-1.9.dev3/tests/test_thumbcachefile.py → dissect_thumbcache-1.10.dev1/tests/test_thumbcache_file.py +18 -13
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tox.ini +4 -17
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/COPYRIGHT +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/LICENSE +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/MANIFEST.in +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/README.md +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/__init__.py +3 -3
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/tools/__init__.py +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect.thumbcache.egg-info/dependency_links.txt +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect.thumbcache.egg-info/entry_points.txt +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect.thumbcache.egg-info/requires.txt +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect.thumbcache.egg-info/top_level.txt +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/setup.cfg +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/__init__.py +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_1280.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_16.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_1920.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_256.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_2560.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_32.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_48.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_768.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_96.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_custom_stream.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_exif.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_idx.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_sr.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_wide.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_wide_alternate.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_1280.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_16.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_1920.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_256.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_2560.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_32.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_48.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_768.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_96.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_custom_stream.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_exif.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_idx.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_sr.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_wide.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_wide_alternate.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_1024.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_256.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_32.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_96.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_idx.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_sr.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_1024.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_16.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_1600.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_256.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_32.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_48.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_96.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_exif.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_idx.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_sr.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_wide.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_wide_alternate.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_vista/thumbcache_1024.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_vista/thumbcache_256.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_vista/thumbcache_32.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_vista/thumbcache_96.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_vista/thumbcache_idx.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_vista/thumbcache_sr.db +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/docs/Makefile +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/docs/conf.py +0 -0
- {dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/docs/index.rst +0 -0
{dissect_thumbcache-1.9.dev3/dissect.thumbcache.egg-info → dissect_thumbcache-1.10.dev1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: dissect.thumbcache
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.dev1
|
|
4
4
|
Summary: A Dissect module implementing parsers for the thumbcache of Windows systems.
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/c_thumbcache.py
RENAMED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from dissect.cstruct import cstruct
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
thumbcache_def = """
|
|
4
6
|
struct INDEX_HEADER_V1 {
|
|
5
7
|
char Signature[4]; // 0x00
|
|
6
8
|
uint32 Version; // 0x04
|
|
@@ -75,4 +77,4 @@ struct CACHE_ENTRY_VISTA {
|
|
|
75
77
|
uint32 Unknown; // 0x28
|
|
76
78
|
}; // 0x2C
|
|
77
79
|
"""
|
|
78
|
-
|
|
80
|
+
c_thumbcache = cstruct().load(thumbcache_def)
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/exceptions.py
RENAMED
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
class Error(Exception):
|
|
2
2
|
"""A generic exception for the thumbcache module."""
|
|
3
3
|
|
|
4
|
-
pass
|
|
5
|
-
|
|
6
4
|
|
|
7
5
|
class NotAnIndexFileError(Error):
|
|
8
6
|
"""Raises if a thumbnail index signature could not be found."""
|
|
9
7
|
|
|
10
|
-
pass
|
|
11
|
-
|
|
12
8
|
|
|
13
9
|
class InvalidSignatureError(Error):
|
|
14
10
|
"""Raises if the signature does not match the expected value."""
|
|
15
11
|
|
|
16
|
-
pass
|
|
17
|
-
|
|
18
12
|
|
|
19
13
|
class UnknownThumbnailTypeError(Error):
|
|
20
14
|
"""Raises if an unknown thumbnail type was found."""
|
|
21
|
-
|
|
22
|
-
pass
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from typing import BinaryIO, Iterator
|
|
3
|
+
from typing import TYPE_CHECKING, BinaryIO
|
|
5
4
|
|
|
6
5
|
from dissect.util import ts
|
|
7
6
|
|
|
8
|
-
from dissect.thumbcache.c_thumbcache import
|
|
7
|
+
from dissect.thumbcache.c_thumbcache import c_thumbcache
|
|
9
8
|
from dissect.thumbcache.exceptions import NotAnIndexFileError
|
|
10
9
|
from dissect.thumbcache.util import ThumbnailType
|
|
11
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from collections.abc import Iterator
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
|
|
12
15
|
INDEX_ENTRIES = {
|
|
13
16
|
ThumbnailType.WINDOWS_7: 5,
|
|
14
17
|
ThumbnailType.WINDOWS_81: 11,
|
|
@@ -29,12 +32,12 @@ class ThumbnailIndex:
|
|
|
29
32
|
self._header = None
|
|
30
33
|
|
|
31
34
|
@property
|
|
32
|
-
def header(self) ->
|
|
35
|
+
def header(self) -> c_thumbcache.INDEX_HEADER_V1 | c_thumbcache.INDEX_HEADER_V2:
|
|
33
36
|
if self._header is None:
|
|
34
37
|
self._header = self._find_header(self.fh)
|
|
35
38
|
return self._header
|
|
36
39
|
|
|
37
|
-
def _find_header(self, fh: BinaryIO) ->
|
|
40
|
+
def _find_header(self, fh: BinaryIO) -> c_thumbcache.INDEX_HEADER_V1 | c_thumbcache.INDEX_HEADER_V2:
|
|
38
41
|
"""Searches for the header signature, and puts ``fh`` at the correct position.
|
|
39
42
|
|
|
40
43
|
From Windows 8.1 onward, the two fields seem to use a 64-bit format field
|
|
@@ -44,19 +47,19 @@ class ThumbnailIndex:
|
|
|
44
47
|
fh: The file to read the header and indexes from.
|
|
45
48
|
|
|
46
49
|
Returns:
|
|
47
|
-
A
|
|
50
|
+
A c_thumbcache.INDEX_HEADER structure.
|
|
48
51
|
|
|
49
52
|
Raises:
|
|
50
53
|
NotAThumbnailIndexFileError: If the ``IMMM`` signature could not be found.
|
|
51
54
|
"""
|
|
52
55
|
position = fh.tell()
|
|
53
|
-
buffer = fh.read(len(
|
|
56
|
+
buffer = fh.read(len(c_thumbcache.INDEX_HEADER_V1))
|
|
54
57
|
offset = buffer.find(self._signature)
|
|
55
58
|
|
|
56
59
|
if offset == MAX_IMM_OFFSET:
|
|
57
60
|
fh.seek(position)
|
|
58
61
|
|
|
59
|
-
header =
|
|
62
|
+
header = c_thumbcache.INDEX_HEADER_V2(fh)
|
|
60
63
|
# From looking at the index files, it has a specific amount of information.
|
|
61
64
|
# It is alligned in the follwing way:
|
|
62
65
|
# INDEX_HEADER_V2
|
|
@@ -68,19 +71,18 @@ class ThumbnailIndex:
|
|
|
68
71
|
|
|
69
72
|
# Read one index entry from the file till only zero bytes
|
|
70
73
|
entry = IndexEntry(fh, header.Version)
|
|
71
|
-
entry.header
|
|
72
|
-
entry.cache_offsets
|
|
74
|
+
_ = entry.header
|
|
75
|
+
_ = entry.cache_offsets
|
|
73
76
|
|
|
74
77
|
# Read offset to first entry
|
|
75
78
|
zero_bytes = len(entry.header) + INDEX_ENTRIES.get(header.Version) * BYTES_IN_NUMBER - len(header)
|
|
76
79
|
fh.read(zero_bytes)
|
|
77
80
|
return header
|
|
78
|
-
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
81
|
+
if offset == 0:
|
|
82
|
+
return c_thumbcache.INDEX_HEADER_V1(buffer)
|
|
83
|
+
raise NotAnIndexFileError(
|
|
84
|
+
f"The index file signature {self._signature!r} could not be found at the expected location."
|
|
85
|
+
)
|
|
84
86
|
|
|
85
87
|
@property
|
|
86
88
|
def version(self) -> int:
|
|
@@ -102,8 +104,8 @@ class ThumbnailIndex:
|
|
|
102
104
|
"""Returns all index entries that are actually used."""
|
|
103
105
|
for _ in range(self.total_entries):
|
|
104
106
|
entry = IndexEntry(self.fh, self.type)
|
|
105
|
-
entry.header
|
|
106
|
-
entry.cache_offsets
|
|
107
|
+
_ = entry.header
|
|
108
|
+
_ = entry.cache_offsets
|
|
107
109
|
|
|
108
110
|
if entry.in_use():
|
|
109
111
|
yield entry
|
|
@@ -119,21 +121,20 @@ class IndexEntry:
|
|
|
119
121
|
@property
|
|
120
122
|
def header(
|
|
121
123
|
self,
|
|
122
|
-
) ->
|
|
124
|
+
) -> c_thumbcache.VISTA_ENTRY | c_thumbcache.WINDOWS7_ENTRY | c_thumbcache.WINDOWS8_ENTRY:
|
|
123
125
|
if not self._header:
|
|
124
126
|
self._header = self._select_header()
|
|
125
127
|
return self._header
|
|
126
128
|
|
|
127
129
|
def _select_header(
|
|
128
130
|
self,
|
|
129
|
-
) ->
|
|
131
|
+
) -> c_thumbcache.VISTA_ENTRY | c_thumbcache.WINDOWS7_ENTRY | c_thumbcache.WINDOWS8_ENTRY:
|
|
130
132
|
"""Selects header version according to the thumbnailtype."""
|
|
131
133
|
if self.type == ThumbnailType.WINDOWS_VISTA:
|
|
132
|
-
return
|
|
133
|
-
|
|
134
|
-
return
|
|
135
|
-
|
|
136
|
-
return c_thumbcache_index.WINDOWS8_ENTRY(self.fh)
|
|
134
|
+
return c_thumbcache.VISTA_ENTRY(self.fh)
|
|
135
|
+
if self.type == ThumbnailType.WINDOWS_7:
|
|
136
|
+
return c_thumbcache.WINDOWS7_ENTRY(self.fh)
|
|
137
|
+
return c_thumbcache.WINDOWS8_ENTRY(self.fh)
|
|
137
138
|
|
|
138
139
|
def in_use(self) -> bool:
|
|
139
140
|
return self.identifier != b"\x00" * IDENTIFIER_BYTES
|
|
@@ -156,7 +157,7 @@ class IndexEntry:
|
|
|
156
157
|
"""
|
|
157
158
|
if not self._data:
|
|
158
159
|
size = INDEX_ENTRIES.get(self.type)
|
|
159
|
-
self._data =
|
|
160
|
+
self._data = c_thumbcache.uint32[size](self.fh)
|
|
160
161
|
if self.type > ThumbnailType.WINDOWS_7:
|
|
161
162
|
# Alignment step
|
|
162
163
|
self.fh.read((size % 2) * BYTES_IN_NUMBER)
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/thumbcache.py
RENAMED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
3
4
|
|
|
4
5
|
from dissect.thumbcache.index import IndexEntry, ThumbnailIndex
|
|
5
6
|
from dissect.thumbcache.thumbcache_file import ThumbcacheEntry, ThumbcacheFile
|
|
6
7
|
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from collections.abc import Iterator
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
7
12
|
|
|
8
13
|
class Thumbcache:
|
|
9
14
|
"""This class combines the thumbnailindex and thumbcachefile.
|
|
@@ -50,8 +55,7 @@ class Thumbcache:
|
|
|
50
55
|
def index_entries(self) -> Iterator[IndexEntry]:
|
|
51
56
|
"""Iterates through all the index entries that are in use."""
|
|
52
57
|
with self.index_file.open("rb") as i_file:
|
|
53
|
-
|
|
54
|
-
yield entry
|
|
58
|
+
yield from ThumbnailIndex(i_file).entries()
|
|
55
59
|
|
|
56
60
|
def _entries_from_offsets(self, offsets: list[int]) -> Iterator[tuple[Path, ThumbcacheEntry]]:
|
|
57
61
|
"""Retrieves Thumbcache entries from a ThumbcacheFile using offsets."""
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/thumbcache_file.py
RENAMED
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any, BinaryIO
|
|
3
|
+
from typing import TYPE_CHECKING, Any, BinaryIO
|
|
4
4
|
|
|
5
|
-
from dissect.thumbcache.c_thumbcache import
|
|
5
|
+
from dissect.thumbcache.c_thumbcache import c_thumbcache
|
|
6
6
|
from dissect.thumbcache.exceptions import (
|
|
7
7
|
InvalidSignatureError,
|
|
8
8
|
UnknownThumbnailTypeError,
|
|
9
9
|
)
|
|
10
10
|
from dissect.thumbcache.util import ThumbnailType, seek_and_return
|
|
11
11
|
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Iterator
|
|
14
|
+
|
|
12
15
|
UNKNOWN_BYTES = 8
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
class ThumbcacheFile:
|
|
16
19
|
__slots__ = [
|
|
17
|
-
"
|
|
20
|
+
"_cached_entries",
|
|
21
|
+
"_entries",
|
|
18
22
|
"_header",
|
|
23
|
+
"fh",
|
|
24
|
+
"offset",
|
|
19
25
|
"signature",
|
|
20
|
-
"type",
|
|
21
26
|
"size",
|
|
22
|
-
"
|
|
23
|
-
"_entries",
|
|
24
|
-
"_cached_entries",
|
|
27
|
+
"type",
|
|
25
28
|
]
|
|
26
29
|
|
|
27
30
|
"""
|
|
@@ -39,8 +42,8 @@ class ThumbcacheFile:
|
|
|
39
42
|
self._header = self._get_header_type(self.fh)
|
|
40
43
|
self._cached_entries: dict[int, ThumbcacheEntry] = {}
|
|
41
44
|
|
|
42
|
-
def _get_header_type(self, fh: BinaryIO) ->
|
|
43
|
-
tmp_header =
|
|
45
|
+
def _get_header_type(self, fh: BinaryIO) -> c_thumbcache.CACHE_HEADER_VISTA | c_thumbcache.CACHE_HEADER:
|
|
46
|
+
tmp_header = c_thumbcache.CACHE_HEADER(fh)
|
|
44
47
|
|
|
45
48
|
if self._signature != tmp_header.Signature:
|
|
46
49
|
raise InvalidSignatureError(
|
|
@@ -48,12 +51,11 @@ class ThumbcacheFile:
|
|
|
48
51
|
)
|
|
49
52
|
|
|
50
53
|
if tmp_header.Version <= ThumbnailType.WINDOWS_7:
|
|
51
|
-
return
|
|
52
|
-
|
|
53
|
-
return tmp_header
|
|
54
|
+
return c_thumbcache.CACHE_HEADER_VISTA(tmp_header.dumps())
|
|
55
|
+
return tmp_header
|
|
54
56
|
|
|
55
57
|
@property
|
|
56
|
-
def header(self) ->
|
|
58
|
+
def header(self) -> c_thumbcache.CACHE_HEADER_VISTA | c_thumbcache.CACHE_HEADER:
|
|
57
59
|
return self._header
|
|
58
60
|
|
|
59
61
|
@property
|
|
@@ -72,15 +74,15 @@ class ThumbcacheFile:
|
|
|
72
74
|
self._cached_entries[key] = item
|
|
73
75
|
return item
|
|
74
76
|
|
|
75
|
-
def __getattribute__(self,
|
|
77
|
+
def __getattribute__(self, name: str) -> Any:
|
|
76
78
|
try:
|
|
77
|
-
return object.__getattribute__(self,
|
|
79
|
+
return object.__getattribute__(self, name)
|
|
78
80
|
except AttributeError:
|
|
79
81
|
pass
|
|
80
82
|
|
|
81
|
-
return getattr(self.header,
|
|
83
|
+
return getattr(self.header, name.capitalize())
|
|
82
84
|
|
|
83
|
-
def entries(self) ->
|
|
85
|
+
def entries(self) -> Iterator[ThumbcacheEntry]:
|
|
84
86
|
with seek_and_return(self.fh, self.fh.tell()):
|
|
85
87
|
try:
|
|
86
88
|
while True:
|
|
@@ -123,10 +125,10 @@ class ThumbcacheEntry:
|
|
|
123
125
|
fh.read(UNKNOWN_BYTES)
|
|
124
126
|
additional_bytes += UNKNOWN_BYTES
|
|
125
127
|
|
|
126
|
-
self.data_checksum: bytes =
|
|
127
|
-
self.header_checksum: bytes =
|
|
128
|
+
self.data_checksum: bytes = c_thumbcache.char[8](fh)
|
|
129
|
+
self.header_checksum: bytes = c_thumbcache.char[8](fh)
|
|
128
130
|
|
|
129
|
-
self.identifier: str =
|
|
131
|
+
self.identifier: str = c_thumbcache.wchar[self._header.IdentifierSize // 2](fh)
|
|
130
132
|
|
|
131
133
|
header_size = len(self._header) + self._header.IdentifierSize + additional_bytes
|
|
132
134
|
|
|
@@ -134,11 +136,10 @@ class ThumbcacheEntry:
|
|
|
134
136
|
|
|
135
137
|
def _get_header(
|
|
136
138
|
self, thumbnail_type: ThumbnailType
|
|
137
|
-
) -> type[
|
|
139
|
+
) -> type[c_thumbcache.CACHE_ENTRY_VISTA | c_thumbcache.CACHE_ENTRY]:
|
|
138
140
|
if thumbnail_type == ThumbnailType.WINDOWS_VISTA:
|
|
139
|
-
return
|
|
140
|
-
|
|
141
|
-
return c_thumbcache_index.CACHE_ENTRY
|
|
141
|
+
return c_thumbcache.CACHE_ENTRY_VISTA
|
|
142
|
+
return c_thumbcache.CACHE_ENTRY
|
|
142
143
|
|
|
143
144
|
@property
|
|
144
145
|
def hash(self) -> str:
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
#!/bin/python3
|
|
2
|
+
from __future__ import annotations
|
|
2
3
|
|
|
3
|
-
from
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from dissect.thumbcache.exceptions import Error
|
|
6
7
|
from dissect.thumbcache.thumbcache_file import ThumbcacheFile
|
|
7
8
|
from dissect.thumbcache.tools.utils import create_argument_parser, write_entry
|
|
8
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from pathlib import Path
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
|
|
14
|
+
def dump_entry_data(path: Path, output_dir: Path) -> None:
|
|
11
15
|
with path.open("rb") as file:
|
|
12
16
|
try:
|
|
13
17
|
cache_file = ThumbcacheFile(file)
|
|
@@ -18,7 +22,7 @@ def dump_entry_data(path: Path, output_dir: Path):
|
|
|
18
22
|
print(e)
|
|
19
23
|
|
|
20
24
|
|
|
21
|
-
def main():
|
|
25
|
+
def main() -> None:
|
|
22
26
|
parser = create_argument_parser("extract raw thumbcache entries")
|
|
23
27
|
args = parser.parse_args()
|
|
24
28
|
path: Path = args.cache_path
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
2
4
|
|
|
3
5
|
from dissect.thumbcache.exceptions import Error
|
|
4
6
|
from dissect.thumbcache.thumbcache import Thumbcache
|
|
5
7
|
from dissect.thumbcache.tools.utils import create_argument_parser, write_entry
|
|
6
8
|
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
7
12
|
|
|
8
|
-
def dump_entry_data_through_index(path: Path, output_dir: Path, prefix: str):
|
|
13
|
+
def dump_entry_data_through_index(path: Path, output_dir: Path, prefix: str) -> None:
|
|
9
14
|
cache = Thumbcache(path=path, prefix=prefix)
|
|
10
15
|
try:
|
|
11
16
|
for location_path, entry in cache.entries():
|
|
@@ -15,7 +20,7 @@ def dump_entry_data_through_index(path: Path, output_dir: Path, prefix: str):
|
|
|
15
20
|
print(e)
|
|
16
21
|
|
|
17
22
|
|
|
18
|
-
def main():
|
|
23
|
+
def main() -> None:
|
|
19
24
|
parser = create_argument_parser("extract indexed entries")
|
|
20
25
|
parser.add_argument(
|
|
21
26
|
"--prefix",
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/tools/utils.py
RENAMED
|
@@ -1,18 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from argparse import ArgumentParser
|
|
2
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from dissect.thumbcache.thumbcache import ThumbcacheEntry
|
|
5
9
|
|
|
6
10
|
|
|
7
|
-
def create_argument_parser(name: str) -> ArgumentParser
|
|
11
|
+
def create_argument_parser(name: str) -> ArgumentParser:
|
|
8
12
|
parser = ArgumentParser(name)
|
|
9
13
|
parser.add_argument("cache_path", type=Path)
|
|
10
|
-
parser.add_argument("--output-dir", "-o", type=Path, default=Path(
|
|
14
|
+
parser.add_argument("--output-dir", "-o", type=Path, default=Path())
|
|
11
15
|
|
|
12
16
|
return parser
|
|
13
17
|
|
|
14
18
|
|
|
15
|
-
def write_entry(output_path: Path, entry: ThumbcacheEntry, file_prefix: str):
|
|
19
|
+
def write_entry(output_path: Path, entry: ThumbcacheEntry, file_prefix: str) -> None:
|
|
16
20
|
output_file = (output_path / f"{entry.hash}/{entry.identifier}_{file_prefix}").with_suffix(".bmp")
|
|
17
21
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
|
18
22
|
with output_file.open("wb") as output:
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import enum
|
|
2
4
|
from contextlib import contextmanager
|
|
3
|
-
from typing import BinaryIO
|
|
5
|
+
from typing import TYPE_CHECKING, BinaryIO
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from collections.abc import Iterator
|
|
4
9
|
|
|
5
10
|
|
|
6
11
|
class ThumbnailType(enum.IntEnum):
|
|
@@ -11,7 +16,7 @@ class ThumbnailType(enum.IntEnum):
|
|
|
11
16
|
|
|
12
17
|
|
|
13
18
|
@contextmanager
|
|
14
|
-
def seek_and_return(fh: BinaryIO, position: int) -> BinaryIO:
|
|
19
|
+
def seek_and_return(fh: BinaryIO, position: int) -> Iterator[BinaryIO]:
|
|
15
20
|
current_position = fh.tell()
|
|
16
21
|
try:
|
|
17
22
|
fh.seek(position)
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1/dissect.thumbcache.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: dissect.thumbcache
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.dev1
|
|
4
4
|
Summary: A Dissect module implementing parsers for the thumbcache of Windows systems.
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License: Affero General Public License v3
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect.thumbcache.egg-info/SOURCES.txt
RENAMED
|
@@ -24,7 +24,7 @@ dissect/thumbcache/tools/utils.py
|
|
|
24
24
|
tests/__init__.py
|
|
25
25
|
tests/test_index.py
|
|
26
26
|
tests/test_thumbcache.py
|
|
27
|
-
tests/
|
|
27
|
+
tests/test_thumbcache_file.py
|
|
28
28
|
tests/data/windows_10/thumbcache_1280.db
|
|
29
29
|
tests/data/windows_10/thumbcache_16.db
|
|
30
30
|
tests/data/windows_10/thumbcache_1920.db
|
|
@@ -45,13 +45,56 @@ dev = [
|
|
|
45
45
|
thumbcache-extract = "dissect.thumbcache.tools.extract_images:main"
|
|
46
46
|
thumbcache-extract-indexed = "dissect.thumbcache.tools.extract_with_index:main"
|
|
47
47
|
|
|
48
|
-
[tool.
|
|
48
|
+
[tool.ruff]
|
|
49
49
|
line-length = 120
|
|
50
|
+
required-version = ">=0.9.0"
|
|
50
51
|
|
|
51
|
-
[tool.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
[tool.ruff.format]
|
|
53
|
+
docstring-code-format = true
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint]
|
|
56
|
+
select = [
|
|
57
|
+
"F",
|
|
58
|
+
"E",
|
|
59
|
+
"W",
|
|
60
|
+
"I",
|
|
61
|
+
"UP",
|
|
62
|
+
"YTT",
|
|
63
|
+
"ANN",
|
|
64
|
+
"B",
|
|
65
|
+
"C4",
|
|
66
|
+
"DTZ",
|
|
67
|
+
"T10",
|
|
68
|
+
"FA",
|
|
69
|
+
"ISC",
|
|
70
|
+
"G",
|
|
71
|
+
"INP",
|
|
72
|
+
"PIE",
|
|
73
|
+
"PYI",
|
|
74
|
+
"PT",
|
|
75
|
+
"Q",
|
|
76
|
+
"RSE",
|
|
77
|
+
"RET",
|
|
78
|
+
"SLOT",
|
|
79
|
+
"SIM",
|
|
80
|
+
"TID",
|
|
81
|
+
"TCH",
|
|
82
|
+
"PTH",
|
|
83
|
+
"PLC",
|
|
84
|
+
"TRY",
|
|
85
|
+
"FLY",
|
|
86
|
+
"PERF",
|
|
87
|
+
"FURB",
|
|
88
|
+
"RUF",
|
|
89
|
+
]
|
|
90
|
+
ignore = ["E203", "B904", "UP024", "ANN002", "ANN003", "ANN204", "ANN401", "SIM105", "TRY003"]
|
|
91
|
+
|
|
92
|
+
[tool.ruff.lint.per-file-ignores]
|
|
93
|
+
"tests/docs/**" = ["INP001"]
|
|
94
|
+
|
|
95
|
+
[tool.ruff.lint.isort]
|
|
96
|
+
known-first-party = ["dissect.thumbcache"]
|
|
97
|
+
known-third-party = ["dissect"]
|
|
55
98
|
|
|
56
99
|
[tool.setuptools]
|
|
57
100
|
license-files = ["LICENSE", "COPYRIGHT"]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import io
|
|
2
4
|
from pathlib import Path
|
|
3
5
|
from unittest.mock import Mock
|
|
@@ -8,12 +10,12 @@ from dissect.thumbcache.exceptions import NotAnIndexFileError
|
|
|
8
10
|
from dissect.thumbcache.index import IndexEntry, ThumbnailIndex, ThumbnailType
|
|
9
11
|
|
|
10
12
|
|
|
11
|
-
def test_index():
|
|
13
|
+
def test_index() -> None:
|
|
12
14
|
ThumbnailIndex(fh=Mock)
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
@pytest.mark.parametrize(
|
|
16
|
-
"path, expected_type",
|
|
18
|
+
("path", "expected_type"),
|
|
17
19
|
[
|
|
18
20
|
(Path("data/windows_vista/thumbcache_idx.db"), ThumbnailType.WINDOWS_VISTA),
|
|
19
21
|
(Path("data/windows_7/thumbcache_idx.db"), ThumbnailType.WINDOWS_7),
|
|
@@ -25,7 +27,7 @@ def test_index():
|
|
|
25
27
|
def test_index_type(
|
|
26
28
|
path: Path,
|
|
27
29
|
expected_type: ThumbnailType,
|
|
28
|
-
):
|
|
30
|
+
) -> None:
|
|
29
31
|
index_path = Path(__file__).parent / path
|
|
30
32
|
|
|
31
33
|
with index_path.open("rb") as ifile:
|
|
@@ -33,13 +35,12 @@ def test_index_type(
|
|
|
33
35
|
assert index.type == expected_type
|
|
34
36
|
|
|
35
37
|
|
|
36
|
-
def test_index_unknown():
|
|
38
|
+
def test_index_unknown() -> None:
|
|
37
39
|
with pytest.raises(NotAnIndexFileError):
|
|
38
|
-
|
|
39
|
-
index.header
|
|
40
|
+
_ = ThumbnailIndex(io.BytesIO(b"UNKNOWN_DATA")).header
|
|
40
41
|
|
|
41
42
|
|
|
42
|
-
def test_index_entry():
|
|
43
|
+
def test_index_entry() -> None:
|
|
43
44
|
index_entry = IndexEntry(io.BytesIO(b"\x00" * 20), ThumbnailType.WINDOWS_VISTA)
|
|
44
45
|
assert not index_entry.in_use()
|
|
45
46
|
|
|
@@ -54,7 +55,7 @@ def test_index_entry():
|
|
|
54
55
|
"data/windows_vista/thumbcache_idx.db",
|
|
55
56
|
],
|
|
56
57
|
)
|
|
57
|
-
def test_get_index_entries(path: str):
|
|
58
|
+
def test_get_index_entries(path: str) -> None:
|
|
58
59
|
idx_file = Path(__file__).parent / path
|
|
59
60
|
with idx_file.open("rb") as index_file:
|
|
60
61
|
index = ThumbnailIndex(index_file)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from pathlib import Path
|
|
2
4
|
|
|
3
5
|
import pytest
|
|
@@ -11,12 +13,12 @@ def thumbcache(path: str) -> Thumbcache:
|
|
|
11
13
|
return Thumbcache(file)
|
|
12
14
|
|
|
13
15
|
|
|
14
|
-
def test_thumbcache():
|
|
16
|
+
def test_thumbcache() -> None:
|
|
15
17
|
assert Thumbcache(Path(__file__).parent / "data/windows_7")
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
@pytest.mark.parametrize(
|
|
19
|
-
"path, expected_mapping",
|
|
21
|
+
("path", "expected_mapping"),
|
|
20
22
|
[
|
|
21
23
|
("data/windows_vista", {0: "32", 1: "96", 2: "256", 3: "1024", 4: "sr"}),
|
|
22
24
|
(
|
|
@@ -60,13 +62,13 @@ def test_thumbcache():
|
|
|
60
62
|
),
|
|
61
63
|
],
|
|
62
64
|
)
|
|
63
|
-
def test_thumbcache_mapping(thumbcache: Thumbcache, expected_mapping: dict):
|
|
65
|
+
def test_thumbcache_mapping(thumbcache: Thumbcache, expected_mapping: dict) -> None:
|
|
64
66
|
for key, value in expected_mapping.items():
|
|
65
67
|
assert value in thumbcache.mapping[key].name
|
|
66
68
|
|
|
67
69
|
|
|
68
70
|
@pytest.mark.parametrize(
|
|
69
|
-
"path, nr_of_entries",
|
|
71
|
+
("path", "nr_of_entries"),
|
|
70
72
|
[
|
|
71
73
|
(
|
|
72
74
|
"data/windows_7",
|
|
@@ -78,16 +80,16 @@ def test_thumbcache_mapping(thumbcache: Thumbcache, expected_mapping: dict):
|
|
|
78
80
|
),
|
|
79
81
|
],
|
|
80
82
|
)
|
|
81
|
-
def test_thumbcache_entries(thumbcache: Thumbcache, nr_of_entries: int):
|
|
83
|
+
def test_thumbcache_entries(thumbcache: Thumbcache, nr_of_entries: int) -> None:
|
|
82
84
|
assert len(list(thumbcache.entries())) == nr_of_entries
|
|
83
85
|
|
|
84
86
|
|
|
85
87
|
@pytest.mark.parametrize(
|
|
86
|
-
"path, offsets, expected_entries",
|
|
88
|
+
("path", "offsets", "expected_entries"),
|
|
87
89
|
[
|
|
88
90
|
("data/windows_7", [0xFFFFFFFF, 0xFFFFFFFF, 152, 0xFFFFFFFF, 0xFFFFFFFF], 1),
|
|
89
91
|
("data/windows_7", [0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF], 0),
|
|
90
92
|
],
|
|
91
93
|
)
|
|
92
|
-
def test_entries_from_offset(thumbcache: Thumbcache, offsets, expected_entries):
|
|
94
|
+
def test_entries_from_offset(thumbcache: Thumbcache, offsets: list[int], expected_entries: int) -> None:
|
|
93
95
|
assert len(list(thumbcache._entries_from_offsets(offsets))) == expected_entries
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from pathlib import Path
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
2
5
|
|
|
3
6
|
import pytest
|
|
4
7
|
|
|
5
|
-
from dissect.thumbcache.c_thumbcache import
|
|
8
|
+
from dissect.thumbcache.c_thumbcache import c_thumbcache
|
|
6
9
|
from dissect.thumbcache.exceptions import (
|
|
7
10
|
InvalidSignatureError,
|
|
8
11
|
UnknownThumbnailTypeError,
|
|
@@ -10,9 +13,12 @@ from dissect.thumbcache.exceptions import (
|
|
|
10
13
|
from dissect.thumbcache.thumbcache_file import ThumbcacheFile
|
|
11
14
|
from dissect.thumbcache.util import ThumbnailType
|
|
12
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from collections.abc import Iterator
|
|
18
|
+
|
|
13
19
|
|
|
14
20
|
@pytest.fixture
|
|
15
|
-
def thumbcache_file(path: str) -> ThumbcacheFile:
|
|
21
|
+
def thumbcache_file(path: str) -> Iterator[ThumbcacheFile]:
|
|
16
22
|
current_path = Path(__file__).parent / "data" / path
|
|
17
23
|
|
|
18
24
|
with current_path.open("rb") as thumb_file:
|
|
@@ -20,7 +26,7 @@ def thumbcache_file(path: str) -> ThumbcacheFile:
|
|
|
20
26
|
|
|
21
27
|
|
|
22
28
|
@pytest.mark.parametrize(
|
|
23
|
-
"path, thumbnail_type",
|
|
29
|
+
("path", "thumbnail_type"),
|
|
24
30
|
[
|
|
25
31
|
("windows_7/thumbcache_32.db", ThumbnailType.WINDOWS_7),
|
|
26
32
|
("windows_10/thumbcache_32.db", ThumbnailType.WINDOWS_10),
|
|
@@ -28,25 +34,24 @@ def thumbcache_file(path: str) -> ThumbcacheFile:
|
|
|
28
34
|
("windows_81/thumbcache_32.db", ThumbnailType.WINDOWS_81),
|
|
29
35
|
],
|
|
30
36
|
)
|
|
31
|
-
def test_thumbcache_version(thumbcache_file: ThumbcacheFile, thumbnail_type: ThumbnailType):
|
|
37
|
+
def test_thumbcache_version(thumbcache_file: ThumbcacheFile, thumbnail_type: ThumbnailType) -> None:
|
|
32
38
|
assert thumbcache_file.version == thumbnail_type
|
|
33
39
|
assert thumbcache_file.signature == b"CMMM"
|
|
34
40
|
|
|
35
41
|
|
|
36
|
-
def test_thumbcache_file_failed():
|
|
42
|
+
def test_thumbcache_file_failed() -> None:
|
|
37
43
|
with pytest.raises(InvalidSignatureError):
|
|
38
44
|
ThumbcacheFile(b"UNKNOWN" + b"\x00" * 20)
|
|
39
45
|
|
|
40
46
|
|
|
41
|
-
def test_unknown_thumbnail_type():
|
|
47
|
+
def test_unknown_thumbnail_type() -> None:
|
|
48
|
+
header = c_thumbcache.CACHE_HEADER(Signature=b"CMMM", Version=0xDEADBEEF)
|
|
42
49
|
with pytest.raises(UnknownThumbnailTypeError):
|
|
43
|
-
|
|
44
|
-
cache_file = ThumbcacheFile(header.dumps())
|
|
45
|
-
cache_file.version
|
|
50
|
+
_ = ThumbcacheFile(header.dumps()).version
|
|
46
51
|
|
|
47
52
|
|
|
48
53
|
@pytest.mark.parametrize(
|
|
49
|
-
"path, entries, size",
|
|
54
|
+
("path", "entries", "size"),
|
|
50
55
|
[
|
|
51
56
|
("windows_7/thumbcache_256.db", 0x3, 0x0118),
|
|
52
57
|
("windows_10/thumbcache_32.db", 0x6, 0),
|
|
@@ -55,7 +60,7 @@ def test_unknown_thumbnail_type():
|
|
|
55
60
|
("windows_vista/thumbcache_32.db", 0x12, 0xDDA8),
|
|
56
61
|
],
|
|
57
62
|
)
|
|
58
|
-
def test_thumbcache_entries(thumbcache_file: ThumbcacheFile, entries: int, size: int):
|
|
63
|
+
def test_thumbcache_entries(thumbcache_file: ThumbcacheFile, entries: int, size: int) -> None:
|
|
59
64
|
assert len(list(thumbcache_file.entries())) == entries
|
|
60
65
|
assert thumbcache_file.size == size
|
|
61
66
|
|
|
@@ -64,7 +69,7 @@ def test_thumbcache_entries(thumbcache_file: ThumbcacheFile, entries: int, size:
|
|
|
64
69
|
"path",
|
|
65
70
|
[("windows_7/thumbcache_256.db")],
|
|
66
71
|
)
|
|
67
|
-
def test_thumbcache_get_entry(thumbcache_file: ThumbcacheFile):
|
|
72
|
+
def test_thumbcache_get_entry(thumbcache_file: ThumbcacheFile) -> None:
|
|
68
73
|
assert thumbcache_file[0x18].hash == "e84eb8f951bc2409"
|
|
69
74
|
|
|
70
75
|
|
|
@@ -72,6 +77,6 @@ def test_thumbcache_get_entry(thumbcache_file: ThumbcacheFile):
|
|
|
72
77
|
"path",
|
|
73
78
|
[("windows_7/thumbcache_256.db")],
|
|
74
79
|
)
|
|
75
|
-
def test_thumbcache_get_entry_failed(thumbcache_file: ThumbcacheFile):
|
|
80
|
+
def test_thumbcache_get_entry_failed(thumbcache_file: ThumbcacheFile) -> None:
|
|
76
81
|
with pytest.raises(InvalidSignatureError):
|
|
77
82
|
thumbcache_file[0x42]
|
|
@@ -32,32 +32,19 @@ 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 tests
|
|
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
|
-
|
|
45
|
+
ruff check dissect tests
|
|
52
46
|
vermin -t=3.9- --no-tips --lint dissect tests
|
|
53
47
|
|
|
54
|
-
[flake8]
|
|
55
|
-
max-line-length = 120
|
|
56
|
-
extend-ignore =
|
|
57
|
-
# See https://github.com/PyCQA/pycodestyle/issues/373
|
|
58
|
-
E203,
|
|
59
|
-
statistics = True
|
|
60
|
-
|
|
61
48
|
[testenv:docs-build]
|
|
62
49
|
allowlist_externals = make
|
|
63
50
|
deps =
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -6,8 +6,8 @@ from dissect.thumbcache.thumbcache_file import ThumbcacheEntry, ThumbcacheFile
|
|
|
6
6
|
__all__ = [
|
|
7
7
|
"Error",
|
|
8
8
|
"IndexEntry",
|
|
9
|
-
"ThumbnailIndex",
|
|
10
|
-
"ThumbcacheFile",
|
|
11
|
-
"ThumbcacheEntry",
|
|
12
9
|
"Thumbcache",
|
|
10
|
+
"ThumbcacheEntry",
|
|
11
|
+
"ThumbcacheFile",
|
|
12
|
+
"ThumbnailIndex",
|
|
13
13
|
]
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/dissect/thumbcache/tools/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_16.db
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_256.db
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_32.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_48.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_768.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_96.db
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_idx.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_10/thumbcache_sr.db
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_16.db
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_256.db
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_32.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_48.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_768.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_96.db
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_idx.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_11/thumbcache_sr.db
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_1024.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_256.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_32.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_96.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_idx.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_7/thumbcache_sr.db
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_16.db
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_256.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_32.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_48.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_96.db
RENAMED
|
File without changes
|
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_idx.db
RENAMED
|
File without changes
|
{dissect_thumbcache-1.9.dev3 → dissect_thumbcache-1.10.dev1}/tests/data/windows_81/thumbcache_sr.db
RENAMED
|
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
|