dissect.target.helpers.configutil

Module Contents

Classes

PeekableIterator

ConfigurationParser

A configuration parser where you can configure certain aspects of the parsing mechanism.

Default

Parse a configuration file specified by separator and comment_prefixes.

CSVish

Parses CSV-ish config files (does not confirm to CSV standard!).

Ini

Parses an ini file according using the built-in Python ConfigParser.

Txt

Read the file into content, and show the bumber of bytes read.

Bin

Read the file into binary and show the number of bytes read.

Xml

Parses an XML file. Ignores any constructor parameters passed from ConfigurationParser.

ListUnwrapper

Provides utility functions to unwrap dictionary objects out of lists.

Json

Parses a JSON file.

Yaml

Parses a Yaml file.

Toml

Parses a Toml file.

Env

Parses .env file contents according to Docker and bash specification.

ScopeManager

A (context)manager for dictionary scoping.

Indentation

This parser is used for files that use a single level of indentation to specify a different scope.

SystemD

A ConfigurationParser that specifically parses systemd configuration files.

Leases

A ConfigurationParser that specifically parses dhclient .leases files.

ParserOptions

ParserConfig

Functions

parse

Parses the content of an path or entry to a dictionary.

parse_config

Attributes

dissect.target.helpers.configutil.HAS_YAML = True
dissect.target.helpers.configutil.HAS_TOML = True
dissect.target.helpers.configutil.log
class dissect.target.helpers.configutil.PeekableIterator(iterable: collections.abc.Iterable[str])
__iter__() PeekableIterator
__next__() str
peek() str | None
class dissect.target.helpers.configutil.ConfigurationParser(collapse: bool | collections.abc.Iterable[str] = False, collapse_inverse: bool = False, separator: tuple[str] = ('=',), comment_prefixes: tuple[str] = (';', '#'))

A configuration parser where you can configure certain aspects of the parsing mechanism.

Parameters:
  • collapse – A bool or an Iterator: If True: it will collapse all the resulting dictionary values. If an Iterable it will collapse on the keys defined in collapse.

  • collapse_inverse – Inverses the collapsing mechanism. Collapse on everything that is not inside collapse.

  • separator – Contains what values it should look for as a separator.

  • comment_prefixes – Contains what constitutes as a comment.

collapse_all
collapse
separator = ('=',)
comment_prefixes = (';', '#')
parsed_data
__getitem__(item: Any) dict | str
__contains__(item: str) bool
abstract parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

get(item: str, default: Any | None = None) Any
read_file(fh: TextIO | io.BytesIO) None

Parse a configuration file.

Raises:

ConfigurationParsingError – If any exception occurs during during the parsing process.

merge(other: ConfigurationParser) ConfigurationParser

Merge the contents of another parser into this one. On conflict, the values of the other parser will be used.

Parameters:

other – The other parser to merge.

Returns:

The merged parser.

keys() collections.abc.KeysView
items() collections.abc.ItemsView
class dissect.target.helpers.configutil.Default(*args, **kwargs)

Bases: ConfigurationParser

Parse a configuration file specified by separator and comment_prefixes.

This parser splits only on the first separator it finds:

key<separator>value     -> {"key": "value"}

key<separator>value

  continuation
                        -> {"key": "value continuation"}

# Unless we collapse values, we add them to a list to not overwrite any values.
key<separator>value1
key<separator>value2
                        -> {key: [value1, value2]}

<empty_space><comment>  -> skip
SEPARATOR
COMMENTS
skip_lines
line_reader(fh: TextIO, strip_comments: bool = True) collections.abc.Iterator[str]
parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.CSVish(*args, fields: tuple[str, Ellipsis], **kwargs)

Bases: Default

Parses CSV-ish config files (does not confirm to CSV standard!).

fields
num_fields
maxsplit
parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.Ini(*args, **kwargs)

Bases: ConfigurationParser

Parses an ini file according using the built-in Python ConfigParser.

parsed_data
parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.Txt(collapse: bool | collections.abc.Iterable[str] = False, collapse_inverse: bool = False, separator: tuple[str] = ('=',), comment_prefixes: tuple[str] = (';', '#'))

Bases: ConfigurationParser

Read the file into content, and show the bumber of bytes read.

parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.Bin(collapse: bool | collections.abc.Iterable[str] = False, collapse_inverse: bool = False, separator: tuple[str] = ('=',), comment_prefixes: tuple[str] = (';', '#'))

Bases: ConfigurationParser

Read the file into binary and show the number of bytes read.

parse_file(fh: io.BytesIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.Xml(collapse: bool | collections.abc.Iterable[str] = False, collapse_inverse: bool = False, separator: tuple[str] = ('=',), comment_prefixes: tuple[str] = (';', '#'))

Bases: ConfigurationParser

Parses an XML file. Ignores any constructor parameters passed from ConfigurationParser.

parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.ListUnwrapper

Provides utility functions to unwrap dictionary objects out of lists.

static unwrap(data: dict | list) dict | list

Transforms a list with dictionaries to a dictionary.

The order of the list is preserved. If no dictionary is found, the list remains untouched:

["value1", "value2"]    -> ["value1", "value2"]

{"data": "value"}       -> {"data": "value"}

[{"data": "value"}]     -> {
                               "list_item0": {
                                    "data": "value"
                               }
                           }
class dissect.target.helpers.configutil.Json(collapse: bool | collections.abc.Iterable[str] = False, collapse_inverse: bool = False, separator: tuple[str] = ('=',), comment_prefixes: tuple[str] = (';', '#'))

Bases: ConfigurationParser

Parses a JSON file.

parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.Yaml(collapse: bool | collections.abc.Iterable[str] = False, collapse_inverse: bool = False, separator: tuple[str] = ('=',), comment_prefixes: tuple[str] = (';', '#'))

Bases: ConfigurationParser

Parses a Yaml file.

parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.Toml(collapse: bool | collections.abc.Iterable[str] = False, collapse_inverse: bool = False, separator: tuple[str] = ('=',), comment_prefixes: tuple[str] = (';', '#'))

Bases: ConfigurationParser

Parses a Toml file.

parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.Env(comments: bool = True, *args, **kwargs)

Bases: ConfigurationParser

Parses .env file contents according to Docker and bash specification.

Does not apply interpolation of substituted values, e.g. foo=${bar} and does not attempt to parse list or dict strings. Does not support dynamic env files, e.g. foo=`bar`. Also does not support multi-line key/value assignments (yet).

References

RE_KV
comments = True
parsed_data: dict | tuple[dict, str | None]
parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.ScopeManager

A (context)manager for dictionary scoping.

This class provides utility functions to keep track of scopes inside a dictionary.

_parents

A dictionary accounting what child belongs to which parent dictionary.

_root

The initial dictionary.

_current

The current dictionary.

_previous

The node before the current (changed) node.

__enter__() typing_extensions.Self
__exit__(type: ScopeManager.__exit__.type[BaseException] | None, value: BaseException | None, traceback: types.TracebackType | None) None
push(name: str, keep_prev: bool = False) Literal[True]

Push a new key to the _current dictionary and return that we did.

pop(keep_prev: bool = False) bool

Pop _current and return whether we changed the _parents dictionary.

update(key: str, value: str) None

Update the _current dictionary with key and value.

update_prev(key: str, value: str) None

Update the _previous dictionary with key and value.

is_root() bool

Utility function to check whether the current dictionary is a root dictionary.

clean() None

Clean up the internal state. This is called automatically when ScopeManager is used as a contextmanager.

class dissect.target.helpers.configutil.Indentation(*args, **kwargs)

Bases: Default

This parser is used for files that use a single level of indentation to specify a different scope.

Examples of these files are the sshd_config file. Where “Match” statements use a single layer of indentation to specify a scope for the key value pairs.

The parser parses this as the following:

key value
  key2 value2
                 -> {"key value": {"key2": "value2"}}
parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.SystemD(*args, **kwargs)

Bases: Indentation

A ConfigurationParser that specifically parses systemd configuration files.

Examples

>>> systemd_data = textwrap.dedent(
        '''
        [Section1]
        Key=Value
        [Section2]
        Key2=Value 2\
            Value 2 continued
        '''
    )
>>> parser = SystemD(io.StringIO(systemd_data))
>>> parser.parser_items
{
    "Section1": {
        "Key": "Value
    },
    "Section2": {
        "Key2": "Value2 Value 2 continued
    }
}
parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.Leases(*args, **kwargs)

Bases: Default

A ConfigurationParser that specifically parses dhclient .leases files.

Examples

>>> Leases = textwrap.dedent(
        '''
        lease {
            interface "eth0"; # A comment that gets ignored
            fixed-address 1.2.3.4;
            option dhcp-lease-time 13337;
            option routers 0.0.0.0;
            option host-name "hostname";
            renew 1 2023/12/31 13:37:00;
            rebind 2 2023/01/01 01:00:00;
            expire 3 2024/01/01 13:37:00;
            # Another comment that gets ignored
        }
        '''
    )
>>> parser = Leases(io.StringIO(lease))
>>> parser.parsed_data
{
    "lease-0": {
        "interface": "eth0",
        "fixed-address": "1.2.3.4"
        "option": {
            "dhcp-lease-time": "13337",
            "routers": "0.0.0.0",
            "host-name": "hostname"
        },
        "renew": "1 2023/12/31 13:37:00",
        "rebind": "2 2023/01/01 01:00:00",
        "expire": "3 2024/01/01 13:37:00",
}
parse_file(fh: TextIO) None

Parse the contents of fh into key/value pairs.

This function should set parsed_data as a side_effect.

Parameters:

fh – The text to parse.

class dissect.target.helpers.configutil.ParserOptions
collapse: bool | set | None = None
collapse_inverse: bool | None = None
separator: tuple[str] | None = None
comment_prefixes: tuple[str] | None = None
class dissect.target.helpers.configutil.ParserConfig
parser: type[ConfigurationParser]
collapse: bool | set | None = None
collapse_inverse: bool | None = None
separator: tuple[str] | None = None
comment_prefixes: tuple[str] | None = None
fields: tuple[str] | None = None
create_parser(options: ParserOptions | None = None) ConfigurationParser
dissect.target.helpers.configutil.MATCH_MAP: dict[str, ParserConfig]
dissect.target.helpers.configutil.CONFIG_MAP: dict[tuple[str, Ellipsis], ParserConfig]
dissect.target.helpers.configutil.KNOWN_FILES: dict[str, type[ConfigurationParser]]
dissect.target.helpers.configutil.parse(path: pathlib.Path, hint: str | None = None, *args, **kwargs) ConfigurationParser

Parses the content of an path or entry to a dictionary.

Parameters:
  • path – The path to either a directory or file.

  • hint – What kind of parser should be used.

  • collapse – Whether it should collapse everything or just a certain set of keys.

  • collapse_inverse – Invert the collapse function to collapse everything but the keys inside collapse.

  • separator – The separator that should be used for parsing.

  • comment_prefixes – What is specified as a comment.

Raises:

FileNotFoundError – If the path is not a file.

dissect.target.helpers.configutil.parse_config(entry: pathlib.Path, hint: str | None = None, options: ParserOptions | None = None) ConfigurationParser