diff --git a/dissect/target/helpers/configutil.py b/dissect/target/helpers/configutil.py index 5eb0e91cf..5272fcbe0 100644 --- a/dissect/target/helpers/configutil.py +++ b/dissect/target/helpers/configutil.py @@ -3,6 +3,7 @@ import io import json import re +import sys from collections import deque from configparser import ConfigParser, MissingSectionHeaderError from dataclasses import dataclass @@ -31,9 +32,20 @@ import yaml PY_YAML = True -except (AttributeError, ImportError): +except ImportError: PY_YAML = False +try: + if sys.version_info < (3, 11): + import tomli as toml + else: + # tomllib is included since python 3.11 + import tomllib as toml # novermin + + HAS_TOML = True +except ImportError: + HAS_TOML = False + def _update_dictionary(current: dict[str, Any], key: str, value: Any) -> None: if prev_value := current.get(key): @@ -408,6 +420,16 @@ def parse_file(self, fh: TextIO) -> None: raise ConfigurationParsingError("Failed to parse file, please install PyYAML.") +class Toml(ConfigurationParser): + """Parses a Toml file.""" + + def parse_file(self, fh: TextIO) -> None: + if HAS_TOML: + self.parsed_data = toml.loads(fh.read()) + else: + raise ConfigurationParsingError("Failed to parse file, please install tomli.") + + class ScopeManager: """A (context)manager for dictionary scoping. @@ -696,6 +718,7 @@ def create_parser(self, options: Optional[ParserOptions] = None) -> Configuratio "sample": ParserConfig(Txt), "systemd": ParserConfig(SystemD), "template": ParserConfig(Txt), + "toml": ParserConfig(Toml), } KNOWN_FILES: dict[str, type[ConfigurationParser]] = { diff --git a/pyproject.toml b/pyproject.toml index 8b59b0d44..6c66b146f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,6 +66,7 @@ full = [ "fusepy", "pycryptodome", "pyyaml", + "tomli; python_version<'3.11'", # dissect.target's caching uses flow.record functionlity which depends on the # zstandard module being available. However flow.record does not define # zstandard as a dependency, nor does it allow zstandard to be installed diff --git a/tests/plugins/general/test_config.py b/tests/plugins/general/test_config.py index 6d81cb731..316e5ac3c 100644 --- a/tests/plugins/general/test_config.py +++ b/tests/plugins/general/test_config.py @@ -75,6 +75,7 @@ def test_collapse_types( ("conf", b"key value"), ("sample", b"currently_just_text"), ("template", b"currently_just_text"), + ("toml", b"key = 'value'"), ], ) def test_as_dict(