dissect.target 3.16.dev19__py3-none-any.whl → 3.16.dev21__py3-none-any.whl

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.
@@ -120,9 +120,9 @@ class ConfigurationFilesystem(VirtualFilesystem):
120
120
  try:
121
121
  config_parser = parse(entry, *args, **kwargs)
122
122
  entry = ConfigurationEntry(self, entry.path, entry, config_parser)
123
- except ConfigurationParsingError:
123
+ except ConfigurationParsingError as e:
124
124
  # If a parsing error gets created, it should return the `entry`
125
- log.debug("Error when parsing %s", entry.path)
125
+ log.debug("Error when parsing %s with message '%s'", entry.path, e)
126
126
 
127
127
  return entry
128
128
 
@@ -220,13 +220,15 @@ class ConfigurationEntry(FilesystemEntry):
220
220
  output_buffer = io.StringIO()
221
221
 
222
222
  if isinstance(values, list):
223
- output_buffer.write(textwrap.indent(text="\n".join(values), prefix=prefix))
223
+ # Explicitly convert the list values to strings
224
+ _text = "\n".join(str(val) for val in values)
225
+ output_buffer.write(textwrap.indent(text=_text, prefix=prefix))
224
226
  elif hasattr(values, "keys"):
225
227
  for key, value in values.items():
226
228
  output_buffer.write(textwrap.indent(key, prefix=prefix) + "\n")
227
229
  output_buffer.write(self._write_value_mapping(value, indentation_nr + 4))
228
230
  else:
229
- output_buffer.write(textwrap.indent(values, prefix=prefix) + "\n")
231
+ output_buffer.write(textwrap.indent(str(values), prefix=prefix) + "\n")
230
232
 
231
233
  return output_buffer.getvalue()
232
234
 
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import io
4
+ import json
4
5
  import re
5
6
  from collections import deque
6
7
  from configparser import ConfigParser, MissingSectionHeaderError
@@ -26,6 +27,13 @@ from dissect.target.exceptions import ConfigurationParsingError, FileNotFoundErr
26
27
  from dissect.target.filesystem import FilesystemEntry
27
28
  from dissect.target.helpers.fsutil import TargetPath
28
29
 
30
+ try:
31
+ import yaml
32
+
33
+ PY_YAML = True
34
+ except (AttributeError, ImportError):
35
+ PY_YAML = False
36
+
29
37
 
30
38
  def _update_dictionary(current: dict[str, Any], key: str, value: Any) -> None:
31
39
  if prev_value := current.get(key):
@@ -151,7 +159,7 @@ class ConfigurationParser:
151
159
  try:
152
160
  self.parse_file(fh)
153
161
  except Exception as e:
154
- raise ConfigurationParsingError from e
162
+ raise ConfigurationParsingError(*e.args) from e
155
163
 
156
164
  if self.collapse_all or self.collapse:
157
165
  self.parsed_data = self._collapse_dict(self.parsed_data)
@@ -329,6 +337,77 @@ class Xml(ConfigurationParser):
329
337
  self.parsed_data = tree
330
338
 
331
339
 
340
+ class ListUnwrapper:
341
+ """Provides utility functions to unwrap dictionary objects out of lists."""
342
+
343
+ @staticmethod
344
+ def unwrap(data: Union[dict, list]) -> Union[dict, list]:
345
+ """Transforms a list with dictionaries to a dictionary.
346
+
347
+ The order of the list is preserved. If no dictionary is found,
348
+ the list remains untouched:
349
+
350
+ ["value1", "value2"] -> ["value1", "value2"]
351
+
352
+ {"data": "value"} -> {"data": "value"}
353
+
354
+ [{"data": "value"}] -> {
355
+ "list_item0": {
356
+ "data": "value"
357
+ }
358
+ }
359
+ """
360
+ orig = ListUnwrapper._unwrap_dict_list(data)
361
+ return ListUnwrapper._unwrap_dict(orig)
362
+
363
+ @staticmethod
364
+ def _unwrap_dict(data: Union[dict, list]) -> Union[dict, list]:
365
+ """Looks for dictionaries and unwraps its values."""
366
+
367
+ if not isinstance(data, dict):
368
+ return data
369
+
370
+ root = dict()
371
+ for key, value in data.items():
372
+ _value = ListUnwrapper._unwrap_dict_list(value)
373
+ if isinstance(_value, dict):
374
+ _value = ListUnwrapper._unwrap_dict(_value)
375
+ root[key] = _value
376
+
377
+ return root
378
+
379
+ @staticmethod
380
+ def _unwrap_dict_list(data: Union[dict, list]) -> Union[dict, list]:
381
+ """Unwraps a list containing dictionaries."""
382
+ if not isinstance(data, list) or not any(isinstance(obj, dict) for obj in data):
383
+ return data
384
+
385
+ return_value = {}
386
+ for idx, elem in enumerate(data):
387
+ return_value[f"list_item{idx}"] = elem
388
+
389
+ return return_value
390
+
391
+
392
+ class Json(ConfigurationParser):
393
+ """Parses a JSON file."""
394
+
395
+ def parse_file(self, fh: TextIO):
396
+ parsed_data = json.load(fh)
397
+ self.parsed_data = ListUnwrapper.unwrap(parsed_data)
398
+
399
+
400
+ class Yaml(ConfigurationParser):
401
+ """Parses a Yaml file."""
402
+
403
+ def parse_file(self, fh: TextIO) -> None:
404
+ if PY_YAML:
405
+ parsed_data = yaml.load(fh, yaml.BaseLoader)
406
+ self.parsed_data = ListUnwrapper.unwrap(parsed_data)
407
+ else:
408
+ raise ConfigurationParsingError("Failed to parse file, please install PyYAML.")
409
+
410
+
332
411
  class ScopeManager:
333
412
  """A (context)manager for dictionary scoping.
334
413
 
@@ -609,7 +688,9 @@ MATCH_MAP: dict[str, ParserConfig] = {
609
688
  CONFIG_MAP: dict[tuple[str, ...], ParserConfig] = {
610
689
  "ini": ParserConfig(Ini),
611
690
  "xml": ParserConfig(Xml),
612
- "json": ParserConfig(Txt),
691
+ "json": ParserConfig(Json),
692
+ "yml": ParserConfig(Yaml),
693
+ "yaml": ParserConfig(Yaml),
613
694
  "cnf": ParserConfig(Default),
614
695
  "conf": ParserConfig(Default, separator=(r"\s",)),
615
696
  "sample": ParserConfig(Txt),
@@ -171,7 +171,14 @@ class ApachePlugin(WebserverPlugin):
171
171
 
172
172
  __namespace__ = "apache"
173
173
 
174
- DEFAULT_LOG_DIRS = ["/var/log/apache2", "/var/log/apache", "/var/log/httpd", "/var/log"]
174
+ DEFAULT_LOG_DIRS = [
175
+ "/var/log/apache2",
176
+ "/var/log/apache",
177
+ "/var/log/httpd",
178
+ "/var/log",
179
+ "sysvol/xampp/apache/logs",
180
+ "/opt/lampp/logs",
181
+ ]
175
182
  ACCESS_LOG_NAMES = ["access.log", "access_log", "httpd-access.log"]
176
183
  ERROR_LOG_NAMES = ["error.log"]
177
184
  DEFAULT_CONFIG_PATHS = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.16.dev19
3
+ Version: 3.16.dev21
4
4
  Summary: This module ties all other Dissect modules together, it provides a programming API and command line tools which allow easy access to various data sources inside disk images or file collections (a.k.a. targets)
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License: Affero General Public License v3
@@ -24,7 +24,7 @@ dissect/target/filesystems/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
24
24
  dissect/target/filesystems/ad1.py,sha256=nEPzaaRsb6bL4ItFo0uLdmdLvrmK9BjqHeD3FOp3WQI,2413
25
25
  dissect/target/filesystems/btrfs.py,sha256=5MBi193ZvclkEQcxDr_sDHfj_FYU_hyYNRL4YqpDu4M,6243
26
26
  dissect/target/filesystems/cb.py,sha256=6LcoJiwsYu1Han31IUzVpZVDTifhTLTx_gLfNpB_p6k,5329
27
- dissect/target/filesystems/config.py,sha256=n1MR7a3tGXszpusLSDxZdTYo8IRLtDC_Xd95zPDTzzA,11295
27
+ dissect/target/filesystems/config.py,sha256=C2JnzBzMqbAjchGFDwURItCeUY7uxkhw1Gen-6cGkAc,11432
28
28
  dissect/target/filesystems/dir.py,sha256=7GRvojL151_Vk9e3vqgZbWE3I8IL9bU6LUKc_xjk6D4,4050
29
29
  dissect/target/filesystems/exfat.py,sha256=PRkZPUVN5NlgB1VetFtywdNgF6Yj5OBtF5a25t-fFvw,5917
30
30
  dissect/target/filesystems/extfs.py,sha256=9Cke-H0CL-SPd3-xvdAgfc3YA5hYso0sq6hm0C9vGII,4640
@@ -42,7 +42,7 @@ dissect/target/filesystems/zip.py,sha256=WT1bQhzX_1MXXVZTKrJniae4xqRqMZ8FsfbvhgG
42
42
  dissect/target/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
43
  dissect/target/helpers/cache.py,sha256=_0w_iPD1OM066Ueyadb70erQW05jNnpJe-bDDN1UyXc,8444
44
44
  dissect/target/helpers/config.py,sha256=6917CZ6eDHaK_tOoiVEIndyhRXO6r6eCBIleq6f47PQ,2346
45
- dissect/target/helpers/configutil.py,sha256=u8pG_6dznwnQwj7JpSH54NcYwLAhFkgdyixoBVTDWM0,22587
45
+ dissect/target/helpers/configutil.py,sha256=t_UNvcWuMMT5C1tut_PgTwCnVUodf6RjhfXP4FSkmdo,25068
46
46
  dissect/target/helpers/cyber.py,sha256=Ki5oSU0GgQxjgC_yWoeieGP7GOY5blQCzNX7vy7Pgas,16782
47
47
  dissect/target/helpers/descriptor_extensions.py,sha256=uT8GwznfDAiIgMM7JKKOY0PXKMv2c0GCqJTCkWFgops,2605
48
48
  dissect/target/helpers/docs.py,sha256=J5U65Y3yOTqxDEZRCdrEmO63XQCeDzOJea1PwPM6Cyc,5146
@@ -137,7 +137,7 @@ dissect/target/plugins/apps/vpn/wireguard.py,sha256=45WvCqQQGrG3DVDH5ghcsGpM_Bom
137
137
  dissect/target/plugins/apps/webhosting/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
138
  dissect/target/plugins/apps/webhosting/cpanel.py,sha256=OeFQnu9GmpffIlFyK-AR2Qf8tjyMhazWEAUyccDU5y0,2979
139
139
  dissect/target/plugins/apps/webserver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
140
- dissect/target/plugins/apps/webserver/apache.py,sha256=ekvztMgL5h-KPCaaRtDxZXX8gEZfJVLjjVjlYgJc9O0,14924
140
+ dissect/target/plugins/apps/webserver/apache.py,sha256=bD6_XObfO7W-cFlLRWyhdwEfw-Y57JBi47rWnXCx-vg,15026
141
141
  dissect/target/plugins/apps/webserver/caddy.py,sha256=qZsAK_tILGvroV4SWkDKc-Otwd41bUEtv9H9TuHmt-0,6422
142
142
  dissect/target/plugins/apps/webserver/citrix.py,sha256=FEPdBteEJeeGg3B95W_27O9wLJVhenEc5A5fSLDmK18,3044
143
143
  dissect/target/plugins/apps/webserver/iis.py,sha256=UwRVzLqnKScijdLoZFfpkSUzKTQosicZpn16q__4QBU,14669
@@ -323,10 +323,10 @@ dissect/target/volumes/luks.py,sha256=OmCMsw6rCUXG1_plnLVLTpsvE1n_6WtoRUGQbpmu1z
323
323
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
324
324
  dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
325
325
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
326
- dissect.target-3.16.dev19.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
327
- dissect.target-3.16.dev19.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
328
- dissect.target-3.16.dev19.dist-info/METADATA,sha256=ezTUDrSsAoMlSs_SOQseXiPZrn28KxWM9-BBa29L788,11113
329
- dissect.target-3.16.dev19.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
330
- dissect.target-3.16.dev19.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
331
- dissect.target-3.16.dev19.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
332
- dissect.target-3.16.dev19.dist-info/RECORD,,
326
+ dissect.target-3.16.dev21.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
327
+ dissect.target-3.16.dev21.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
328
+ dissect.target-3.16.dev21.dist-info/METADATA,sha256=P5IeEWD-JvFiTMQeMulDT6W2H5J0Dvo8DbB5T1Cwyjg,11113
329
+ dissect.target-3.16.dev21.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
330
+ dissect.target-3.16.dev21.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
331
+ dissect.target-3.16.dev21.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
332
+ dissect.target-3.16.dev21.dist-info/RECORD,,