Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion dissect/database/ese/ese.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
from dissect.database.ese.c_ese import c_ese, pgnoFDPMSO, ulDAEMagic
from dissect.database.ese.exception import InvalidDatabase
from dissect.database.ese.page import Page
from dissect.database.ese.table import Catalog, Table
from dissect.database.ese.table import Catalog

if TYPE_CHECKING:
from collections.abc import Iterator

from dissect.database.ese.table import Table


class ESE:
"""ESE database class.
Expand Down
1 change: 1 addition & 0 deletions dissect/database/ese/lcmapstring.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Based on Wine source
# https://github.com/wine-mirror/wine/blob/master/dlls/kernelbase/locale.c
# http://www.flounder.com/localeexplorer.htm
from __future__ import annotations

from enum import IntEnum, IntFlag

Expand Down
3 changes: 2 additions & 1 deletion dissect/database/ese/ntds/objects/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
from functools import cached_property
from typing import TYPE_CHECKING, Any, ClassVar

from dissect.database.ese.ntds.util import DN, InstanceType, SystemFlags, decode_value
from dissect.database.ese.ntds.util import InstanceType, decode_value

if TYPE_CHECKING:
from collections.abc import Iterator
from datetime import datetime

from dissect.database.ese.ntds.database import Database
from dissect.database.ese.ntds.sd import SecurityDescriptor
from dissect.database.ese.ntds.util import DN, SystemFlags
from dissect.database.ese.record import Record


Expand Down
3 changes: 2 additions & 1 deletion dissect/database/ese/ntds/objects/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
from typing import TYPE_CHECKING

from dissect.database.ese.ntds.objects.organizationalperson import OrganizationalPerson
from dissect.database.ese.ntds.util import SAMAccountType, UserAccountControl
from dissect.database.ese.ntds.util import UserAccountControl

if TYPE_CHECKING:
from collections.abc import Iterator

from dissect.database.ese.ntds.objects.group import Group
from dissect.database.ese.ntds.objects.object import Object
from dissect.database.ese.ntds.util import SAMAccountType


class User(OrganizationalPerson):
Expand Down
1 change: 0 additions & 1 deletion dissect/database/ese/ntds/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ def load(self, db: Database) -> None:
Args:
db: The database instance to load the schema from.
"""

# Load the schema entries from the DMD object
# This _should_ have all the attribute and class schema entries
# We used to perform an index search on objectClass (ATTc0, INDEX_00000000), but apparently
Expand Down
3 changes: 2 additions & 1 deletion dissect/database/ese/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
from dissect.database.ese.cursor import RawCursor
from dissect.database.ese.index import Index
from dissect.database.ese.record import Record
from dissect.database.ese.util import COLUMN_TYPE_MAP, ColumnType, RecordValue
from dissect.database.ese.util import COLUMN_TYPE_MAP

if TYPE_CHECKING:
from collections.abc import Iterator

from dissect.database.ese.cursor import Cursor
from dissect.database.ese.ese import ESE
from dissect.database.ese.page import Page
from dissect.database.ese.util import ColumnType, RecordValue


class Table:
Expand Down
3 changes: 2 additions & 1 deletion dissect/database/ese/tools/sru.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
from dissect.util.ts import oatimestamp, wintimestamp

from dissect.database.ese.ese import ESE
from dissect.database.ese.record import Record, serialise_record_column_values
from dissect.database.ese.record import serialise_record_column_values

if TYPE_CHECKING:
from collections.abc import Iterator

from dissect.database.ese.record import Record
from dissect.database.ese.table import Table
from dissect.database.ese.util import RecordValue

Expand Down
11 changes: 8 additions & 3 deletions dissect/database/ese/tools/ual.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
from __future__ import annotations

import argparse
import datetime
import ipaddress
import json
from collections.abc import Iterator
from pathlib import Path
from typing import BinaryIO
from typing import TYPE_CHECKING, BinaryIO

from dissect.util.ts import wintimestamp

from dissect.database.ese.ese import ESE
from dissect.database.ese.table import Table
from dissect.database.ese.util import RecordValue

if TYPE_CHECKING:
from collections.abc import Iterator

from dissect.database.ese.table import Table

UalValue = RecordValue | ipaddress.IPv4Address | ipaddress.IPv6Interface | tuple[datetime.datetime]

SKIP_TABLES = [
Expand Down
3 changes: 0 additions & 3 deletions dissect/database/sqlite3/encryption/sqlcipher/sqlcipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ def __init__(self, sqlcipher: SQLCipher):

def _read(self, offset: int, length: int) -> bytes:
"""Calculates which pages to read from based on the given offset and length. Returns decrypted bytes."""

start_page = offset // self.align
num_pages = length // self.align
return b"".join(
Expand All @@ -191,7 +190,6 @@ def _read_page(self, page_num: int, verify_hmac: bool = False) -> bytes:
References:
- https://github.com/sqlcipher/sqlcipher-tools/blob/master/decrypt.c
"""

if page_num < 1:
raise ValueError("The first page number is 1")

Expand Down Expand Up @@ -294,7 +292,6 @@ class SQLCipher1(SQLCipher):

def derive_key(passphrase: bytes, salt: bytes, kdf_iter: int, kdf_algo: str | None) -> bytes:
"""Derive the database key as SQLCipher would using PBKDF2."""

if not kdf_iter or not kdf_algo:
return passphrase

Expand Down
14 changes: 7 additions & 7 deletions dissect/database/sqlite3/sqlite3.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@
NoCellData,
)
from dissect.database.sqlite3.util import parse_table_columns_constraints
from dissect.database.sqlite3.wal import WAL, Checkpoint
from dissect.database.sqlite3.wal import WAL

if TYPE_CHECKING:
from collections.abc import Iterator
from types import TracebackType

from typing_extensions import Self

from dissect.database.sqlite3.wal import Checkpoint

ENCODING = {
1: "utf-8",
2: "utf-16-le",
Expand Down Expand Up @@ -259,7 +261,7 @@ def __init__(self, name: str, description: str):
self.default_value = self._parse_default_value_from_description(description)

def _parse_default_value_from_description(self, description: str) -> bool | str | int | float | None:
"""Find the default from the description string"""
"""Find the default from the description string."""
if "DEFAULT" not in description.upper():
return None

Expand All @@ -275,14 +277,13 @@ def _tokenize(self, description: str) -> list[str]:
return [x for x in tokens if x and x != " "]

def _get_default_value(self, tokens: list[str]) -> str:
"""Retrieve the default from the tokens"""

"""Retrieve the default from the tokens."""
# The +1 is to account for the space after the default
value_index = [x.upper() for x in tokens].index("DEFAULT") + 1
return tokens[value_index]

def _parse_default_value(self, value: str) -> bool | str | int | float | None:
"""Parses the default value
"""Parses the default value.

The value can hold an expression surrounded by ().
This can be a literal, so these values get stripped.
Expand All @@ -293,7 +294,7 @@ def _parse_default_value(self, value: str) -> bool | str | int | float | None:
return None

def _parse_literal(self, value: str) -> bool | str | int | float:
"""Tries to convert a literal from a string to any type
"""Tries to convert a literal from a string to any type.

CURRENT_(TIME|DATE|TIMESTAMP) isn't being taken into account.
"""
Expand Down Expand Up @@ -385,7 +386,6 @@ def _match_columns_to_values(self, columns: list[Column], values: list[Any]) ->
If there are any cell values with unknown column names
they get added to the unknown list.
"""

row_values = {}
unknowns = []

Expand Down
1 change: 0 additions & 1 deletion dissect/database/sqlite3/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ def parse_table_columns_constraints(sql: str) -> tuple[str | None, list[str], li

def split_column_def(sql: str, column_def: str) -> tuple[str, str]:
"""Splits the column definition to name and constraint."""

column_parts = column_def.split(maxsplit=1)
if not column_parts:
raise InvalidSQL(f"Not a valid CREATE TABLE definition: empty column definition in {sql!r}")
Expand Down
22 changes: 20 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,33 @@ select = [
"SLOT",
"SIM",
"TID",
"TCH",
"TC",
"PTH",
"PLC",
"TRY",
"FLY",
"PERF",
"FURB",
"RUF",
"D"
]
ignore = ["E203", "B904", "UP024", "ANN002", "ANN003", "ANN204", "ANN401", "SIM105", "TRY003"]
ignore = [
"E203", "B904", "UP024", "ANN002", "ANN003", "ANN204", "ANN401", "SIM105", "TRY003", "PLC0415",
# Ignore some pydocstyle rules for now as they require a larger cleanup
"D1",
"D205",
"D301",
"D417",
# Seems bugged: https://github.com/astral-sh/ruff/issues/16824
"D402",
]
future-annotations = true

[tool.ruff.lint.pydocstyle]
convention = "google"

[tool.ruff.lint.flake8-type-checking]
strict = true

[tool.ruff.lint.per-file-ignores]
"tests/_docs/**" = ["INP001"]
Expand All @@ -125,6 +142,7 @@ ignore = ["E203", "B904", "UP024", "ANN002", "ANN003", "ANN204", "ANN401", "SIM1
[tool.ruff.lint.isort]
known-first-party = ["dissect.database"]
known-third-party = ["dissect"]
required-imports = ["from __future__ import annotations"]

[tool.setuptools.packages.find]
include = ["dissect.*"]
Expand Down
2 changes: 2 additions & 0 deletions tests/_docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

project = "dissect.database"

extensions = [
Expand Down
2 changes: 2 additions & 0 deletions tests/ese/test_cursor.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from typing import BinaryIO

from dissect.database.ese.ese import ESE
Expand Down
2 changes: 2 additions & 0 deletions tests/ese/test_page.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from unittest.mock import Mock

from dissect.database.ese.c_ese import c_ese
Expand Down
1 change: 0 additions & 1 deletion tests/ese/test_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ def test_parse_value_encoding(windows_search_db: BinaryIO) -> None:
Resources:
- https://github.com/fox-it/dissect.esedb/pull/48
"""

db = ESE(windows_search_db)
table = db.table("SystemIndex_PropertyStore")

Expand Down
2 changes: 2 additions & 0 deletions tests/ese/test_table.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from unittest.mock import MagicMock

from dissect.database.ese.table import Table
Expand Down
2 changes: 0 additions & 2 deletions tests/sqlite3/test_sqlcipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ def _assert_sqlite_db(sqlite: SQLite3) -> None:
)
def test_decrypt_community(cipher: Callable, path_str: str, kwargs: dict) -> None:
"""Test if we can parse a SQLCipher (4.5.6 community) encrypted database."""

path = absolute_path("_data/sqlite3/encryption/sqlcipher/" + path_str)

with pytest.raises(SQLCipherError, match="Decryption of SQLCipher database failed"):
Expand All @@ -79,7 +78,6 @@ def test_decrypt_community(cipher: Callable, path_str: str, kwargs: dict) -> Non

def test_decrypt_community_plaintext_header() -> None:
"""Test if we can parse and decrypt a SQLCipher 4.5.6 database with a 32-byte plaintext header."""

path = absolute_path("_data/sqlite3/encryption/sqlcipher/aes256_hmac_sha512_kdf_256000_plain_header.sqlite")
salt = bytes.fromhex("01010101010101010101010101010101")

Expand Down
1 change: 0 additions & 1 deletion tests/sqlite3/test_sqlite3.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ def test_cell_overflow_reserved_page_size_regression() -> None:
>>> con.commit()
... con.close()
"""

db = sqlite3.SQLite3(absolute_path("_data/sqlite3/overflow.db"))
assert db.header.reserved_size == 32
assert db.header.page_size == 4096
Expand Down
1 change: 0 additions & 1 deletion tests/sqlite3/test_wal.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ def test_wal_page_count() -> None:
>>> con.commit()
# Copy page_count.db* files before closing
"""

db = sqlite3.SQLite3(absolute_path("_data/sqlite3/page_count.db"))
table = db.table("t1")
assert table.sql == "CREATE TABLE t1 (a, b)"
Expand Down
Loading