dissect.target 3.15.dev2__py3-none-any.whl → 3.15.dev4__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
dissect/target/plugin.py CHANGED
@@ -292,18 +292,43 @@ class OSPlugin(Plugin):
292
292
  This provides a base class for certain common functions of OS's, which each OS plugin has to implement separately.
293
293
 
294
294
  For example, it provides an interface for retrieving the hostname and users of a target.
295
+
296
+ All derived classes MUST implement ALL the classmethods and exported
297
+ methods with the same ``@classmethod`` or ``@export(...)`` annotation.
295
298
  """
296
299
 
300
+ def __init_subclass__(cls, **kwargs):
301
+ # Note that cls is the subclass
302
+ super().__init_subclass__(**kwargs)
303
+
304
+ for os_method in get_nonprivate_attributes(OSPlugin):
305
+ if isinstance(os_method, property):
306
+ os_method = os_method.fget
307
+ os_docstring = os_method.__doc__
308
+
309
+ method = getattr(cls, os_method.__name__, None)
310
+ if isinstance(method, property):
311
+ method = method.fget
312
+ # This works as None has a __doc__ property (which is None).
313
+ docstring = method.__doc__
314
+
315
+ if method and not docstring:
316
+ if hasattr(method, "__func__"):
317
+ method = method.__func__
318
+ method.__doc__ = os_docstring
319
+
297
320
  def check_compatible(self) -> bool:
298
- """OSPlugin's use a different compatibility check, override the default one."""
321
+ """OSPlugin's use a different compatibility check, override the one from the :class:`Plugin` class.
322
+
323
+ Returns:
324
+ This function always returns ``True``.
325
+ """
299
326
  return True
300
327
 
301
328
  @classmethod
302
329
  def detect(cls, fs: Filesystem) -> Optional[Filesystem]:
303
330
  """Provide detection of this OSPlugin on a given filesystem.
304
331
 
305
- Note: must be implemented as a classmethod.
306
-
307
332
  Args:
308
333
  fs: :class:`~dissect.target.filesystem.Filesystem` to detect the OS on.
309
334
 
@@ -316,11 +341,9 @@ class OSPlugin(Plugin):
316
341
  def create(cls, target: Target, sysvol: Filesystem) -> OSPlugin:
317
342
  """Initiate this OSPlugin with the given target and detected filesystem.
318
343
 
319
- Note: must be implemented as a classmethod.
320
-
321
344
  Args:
322
- target: The Target object.
323
- sysvol: The filesystem that was detected in the detect() function.
345
+ target: The :class:`~dissect.target.target.Target` object.
346
+ sysvol: The filesystem that was detected in the ``detect()`` function.
324
347
 
325
348
  Returns:
326
349
  An instantiated version of the OSPlugin.
@@ -329,9 +352,7 @@ class OSPlugin(Plugin):
329
352
 
330
353
  @export(property=True)
331
354
  def hostname(self) -> Optional[str]:
332
- """Required OS function.
333
-
334
- Implementations must be decorated with ``@export(property=True)``.
355
+ """Return the target's hostname.
335
356
 
336
357
  Returns:
337
358
  The hostname as string.
@@ -340,9 +361,7 @@ class OSPlugin(Plugin):
340
361
 
341
362
  @export(property=True)
342
363
  def ips(self) -> list[str]:
343
- """Required OS function.
344
-
345
- Implementations must be decorated with ``@export(property=True)``.
364
+ """Return the IP addresses configured in the target.
346
365
 
347
366
  Returns:
348
367
  The IPs as list.
@@ -351,9 +370,7 @@ class OSPlugin(Plugin):
351
370
 
352
371
  @export(property=True)
353
372
  def version(self) -> Optional[str]:
354
- """Required OS function.
355
-
356
- Implementations must be decorated with ``@export(property=True)``.
373
+ """Return the target's OS version.
357
374
 
358
375
  Returns:
359
376
  The OS version as string.
@@ -362,9 +379,7 @@ class OSPlugin(Plugin):
362
379
 
363
380
  @export(record=EmptyRecord)
364
381
  def users(self) -> list[Record]:
365
- """Required OS function.
366
-
367
- Implementations must be decorated with @export.
382
+ """Return the users available in the target.
368
383
 
369
384
  Returns:
370
385
  A list of user records.
@@ -373,9 +388,7 @@ class OSPlugin(Plugin):
373
388
 
374
389
  @export(property=True)
375
390
  def os(self) -> str:
376
- """Required OS function.
377
-
378
- Implementations must be decorated with ``@export(property=True)``.
391
+ """Return a slug of the target's OS name.
379
392
 
380
393
  Returns:
381
394
  A slug of the OS name, e.g. 'windows' or 'linux'.
@@ -384,9 +397,7 @@ class OSPlugin(Plugin):
384
397
 
385
398
  @export(property=True)
386
399
  def architecture(self) -> Optional[str]:
387
- """Required OS function.
388
-
389
- Implementations must be decorated with ``@export(property=True)``.
400
+ """Return a slug of the target's OS architecture.
390
401
 
391
402
  Returns:
392
403
  A slug of the OS architecture, e.g. 'x86_32-unix', 'MIPS-linux' or
@@ -1128,29 +1139,45 @@ def find_plugin_functions(
1128
1139
  ignore_load_errors = kwargs.get("ignore_load_errors", False)
1129
1140
 
1130
1141
  for pattern in patterns.split(","):
1131
- # backward compatibility fix for namespace-level plugins (i.e. chrome)
1142
+ # Backward compatibility fix for namespace-level plugins (i.e. chrome)
1143
+ # If an exact namespace match is found, the pattern is changed to the tree to that namespace.
1144
+ # Examples:
1145
+ # -f browser -> apps.browser.browser
1146
+ # -f iexplore -> apps.browser.iexplore
1147
+ namespace_match = False
1132
1148
  for index_name, func in functions.items():
1133
1149
  if func["namespace"] == pattern:
1134
- pattern = func["module"] + "*"
1150
+ pattern = func["module"]
1151
+ namespace_match = True
1152
+ break
1135
1153
 
1136
1154
  wildcard = any(char in pattern for char in ["*", "!", "?", "[", "]"])
1137
1155
  treematch = pattern.split(".")[0] in rootset and pattern != "os"
1138
1156
  exact_match = pattern in functions
1139
1157
 
1140
- # Allow for exact matches, otherwise you cannot reach documented namespace plugins like
1141
- # browsers.browser.downloads. You can *always* run these using the namespace/classic-style like:
1142
- # browser.downloads (but -l lists them in the tree for documentation purposes so it would be misleading
1143
- # not to allow tree access as well). Note that these tree items will never respond to wildcards though
1144
- # (browsers.browser.* won't work) to avoid duplicate results.
1145
- if exact_match:
1158
+ # Allow for exact and namespace matches even if the plugin does not want to be found, otherwise you cannot
1159
+ # reach documented namespace plugins like apps.browser.browser.downloads.
1160
+ # You can *always* run these using the namespace/classic-style like: browser.downloads (but -l lists them
1161
+ # in the tree for documentation purposes so it would be misleading not to allow tree access as well).
1162
+ #
1163
+ # Note that these tree items will never respond to wildcards though to avoid duplicate results, e.g. when
1164
+ # querying apps.browser.*, this also means apps.browser.browser.* won't work.
1165
+ if exact_match or namespace_match:
1146
1166
  show_hidden = True
1147
1167
 
1148
- if treematch and not wildcard and not exact_match:
1149
- # Examples:
1150
- # -f browsers -> browsers* (the whole package)
1151
- # -f apps.webservers.iis -> apps.webservers.iis* (logs etc)
1152
- # We do not include a dot because that does not work if the full path is given:
1153
- # -f apps.webservers.iis.logs != apps.webservers.iis.logs.* (does not work)
1168
+ # Change the treematch pattern into an fnmatch-able pattern to give back all functions from the sub-tree
1169
+ # (if there is a subtree).
1170
+ #
1171
+ # Examples:
1172
+ # -f browser -> apps.browser.browser* (the whole package, due to a namespace match)
1173
+ # -f apps.webservers.iis -> apps.webservers.iis* (logs etc)
1174
+ # -f apps.webservers.iis.logs -> apps.webservers.iis.logs* (only the logs, there is no subtree)
1175
+ # We do not include a dot because that does not work if the full path is given:
1176
+ # -f apps.webservers.iis.logs != apps.webservers.iis.logs.* (does not work)
1177
+ #
1178
+ # In practice a namespace_match would almost always also be a treematch, except when the namespace plugin
1179
+ # is in the root of the plugin tree.
1180
+ if (treematch or namespace_match) and not wildcard and not exact_match:
1154
1181
  pattern += "*"
1155
1182
 
1156
1183
  if wildcard or treematch:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dissect.target
3
- Version: 3.15.dev2
3
+ Version: 3.15.dev4
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
@@ -3,7 +3,7 @@ dissect/target/container.py,sha256=9ixufT1_0WhraqttBWwQjG80caToJqvCX8VjFk8d5F0,9
3
3
  dissect/target/exceptions.py,sha256=VVW_Rq_vQinapz-2mbJ3UkxBEZpb2pE_7JlhMukdtrY,2877
4
4
  dissect/target/filesystem.py,sha256=oCPNw09I3odf69HKkqph6EM5-AywAQIn9UPO-BxtbpY,53445
5
5
  dissect/target/loader.py,sha256=4ZdX-QJY83NPswTyNG31LUwYXdV1tuByrR2vKKg7d5k,7214
6
- dissect/target/plugin.py,sha256=F-VHirvGu0iX2-TOJWx-THzzhfo712oiARt7zXOzWqE,45855
6
+ dissect/target/plugin.py,sha256=MyBjC7uJ-qml9SQMQ6xsNMdudsOFNJiHNMRn-AFi_pM,47405
7
7
  dissect/target/report.py,sha256=06uiP4MbNI8cWMVrC1SasNS-Yg6ptjVjckwj8Yhe0Js,7958
8
8
  dissect/target/target.py,sha256=CuqLTD3fwr4HIxtDgN_fwJ3UHSqe5PhNJlLTVGsluB8,31908
9
9
  dissect/target/volume.py,sha256=aQZAJiny8jjwkc9UtwIRwy7nINXjCxwpO-_UDfh6-BA,15801
@@ -305,10 +305,10 @@ dissect/target/volumes/luks.py,sha256=v_mHW05KM5iG8JDe47i2V4Q9O0r4rnAMA9m_qc9cYw
305
305
  dissect/target/volumes/lvm.py,sha256=wwQVR9I3G9YzmY6UxFsH2Y4MXGBcKL9aayWGCDTiWMU,2269
306
306
  dissect/target/volumes/md.py,sha256=j1K1iKmspl0C_OJFc7-Q1BMWN2OCC5EVANIgVlJ_fIE,1673
307
307
  dissect/target/volumes/vmfs.py,sha256=-LoUbn9WNwTtLi_4K34uV_-wDw2W5hgaqxZNj4UmqAQ,1730
308
- dissect.target-3.15.dev2.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
309
- dissect.target-3.15.dev2.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
310
- dissect.target-3.15.dev2.dist-info/METADATA,sha256=XCTfv2LwZTgA3EKVzxMYwgeOCdSa6vHIRGCGut_SRBE,11106
311
- dissect.target-3.15.dev2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
312
- dissect.target-3.15.dev2.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
313
- dissect.target-3.15.dev2.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
314
- dissect.target-3.15.dev2.dist-info/RECORD,,
308
+ dissect.target-3.15.dev4.dist-info/COPYRIGHT,sha256=m-9ih2RVhMiXHI2bf_oNSSgHgkeIvaYRVfKTwFbnJPA,301
309
+ dissect.target-3.15.dev4.dist-info/LICENSE,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
310
+ dissect.target-3.15.dev4.dist-info/METADATA,sha256=ZHcCCAily7wTHdfI01lHfl1RXkpa00HXb_oUyZUtO3M,11106
311
+ dissect.target-3.15.dev4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
312
+ dissect.target-3.15.dev4.dist-info/entry_points.txt,sha256=tvFPa-Ap-gakjaPwRc6Fl6mxHzxEZ_arAVU-IUYeo_s,447
313
+ dissect.target-3.15.dev4.dist-info/top_level.txt,sha256=Mn-CQzEYsAbkxrUI0TnplHuXnGVKzxpDw_po_sXpvv4,8
314
+ dissect.target-3.15.dev4.dist-info/RECORD,,