mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-08 02:37:39 +02:00
Convert configuration options over to requirements.
This commit is contained in:
@@ -5,81 +5,45 @@ Created on 7 May 2013
|
||||
"""
|
||||
import re
|
||||
|
||||
from volatility.framework.interfaces.config import GenericRequirement, ConfigurationInterface
|
||||
from volatility.framework.interfaces.config import GenericRequirement
|
||||
|
||||
|
||||
class BooleanRequirement(GenericRequirement):
|
||||
def __init__(self, *args, **kwargs):
|
||||
GenericRequirement.__init__(*args, **kwargs)
|
||||
def check_value(self, value, context):
|
||||
if not isinstance(self.value, bool):
|
||||
raise TypeError(self.name + " requirement only accepts a boolean type")
|
||||
|
||||
def set_value(self, value):
|
||||
self._value = bool(value)
|
||||
|
||||
|
||||
class AddressSpaceRequirement(GenericRequirement):
|
||||
class TranslationLayerRequirement(GenericRequirement):
|
||||
"""Class maintaining the limitations on what sort of address spaces are acceptable"""
|
||||
|
||||
# TODO: derive acceptable OSes from the address_space information
|
||||
# TODO: derive acceptable arches from the available layers
|
||||
def __init__(self, layer_name, astype, os, architectures, *args, **kwargs):
|
||||
GenericRequirement.__init__(self, *args, **kwargs)
|
||||
self.layer_name = layer_name
|
||||
self.astype = astype
|
||||
self.os = os
|
||||
def __init__(self, name, layer_type, os_type, architectures, *args, **kwargs):
|
||||
GenericRequirement.__init__(self, name, *args, **kwargs)
|
||||
self.layer_type = layer_type
|
||||
self.os = os_type
|
||||
self.arches = architectures
|
||||
|
||||
def check_value(self, value, context):
|
||||
"""Validate that the value is a valid layer name and that the layer adheres to the requirements"""
|
||||
|
||||
class ListRequirement(GenericRequirement):
|
||||
def __init__(self, min_elements, max_elements, element_type, *args, **kwargs):
|
||||
GenericRequirement.__init__(self, *args, **kwargs)
|
||||
self.element_type = any([self._type_check(element_type, BooleanRequirement)])
|
||||
if isinstance(element_type, ListRequirement):
|
||||
raise TypeError("ListRequirements cannot contain ListRequirements")
|
||||
self.element_type = self._type_check(element_type, GenericRequirement)
|
||||
self.min_elements = min_elements
|
||||
self.max_elements = max_elements
|
||||
|
||||
def set_value(self, value):
|
||||
def check_value(self, value, context):
|
||||
self._type_check(value, list)
|
||||
all([self._type_check(element, self.element_type) for element in value])
|
||||
if not all([self._type_check(element, self.element_type) for element in value]):
|
||||
raise TypeError("At least one element in the list is not of the correct type.")
|
||||
if not (self.min_elements <= len(value) <= self.max_elements):
|
||||
raise TypeError("List option provided more or less elements than allowed.")
|
||||
self._value = value
|
||||
[self.element_type.check_value(element, context) for element in value]
|
||||
|
||||
|
||||
# TODO: OptionTypes such as choice, list and so on
|
||||
|
||||
|
||||
class Group(ConfigurationInterface):
|
||||
"""Class to handle configuration groups, contains options"""
|
||||
|
||||
def __init__(self, name = None):
|
||||
self.__setattr__('_mapping', [], True)
|
||||
self.__setattr__('_name', name, True)
|
||||
if False:
|
||||
# Code here for IDEs that attempt to figure out what's going on with all the magic we're doing
|
||||
self._mapping = None
|
||||
ConfigurationInterface.__init__(self, name)
|
||||
|
||||
@property
|
||||
def keys(self):
|
||||
return self._mapping
|
||||
|
||||
def __setattr__(self, key, value, force = False):
|
||||
"""Type checks values, and only allows those whose name matches their key"""
|
||||
if not force:
|
||||
if key == 'name':
|
||||
raise KeyError("Name is a reserved attribute of Configuration items.")
|
||||
|
||||
self._type_check(value, ConfigurationInterface)
|
||||
if not re.match('^[A-Za-z][A-Za-z0-9_]*$', value.name):
|
||||
raise KeyError("Configuration item names must only be lowercase letters.")
|
||||
if key != value.name:
|
||||
raise KeyError("Key and value.name must match")
|
||||
self._mapping.append(key)
|
||||
return super(Group, self).__setattr__(key, value)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Group(name = 'volatility')
|
||||
root.core = Group(name = 'core')
|
||||
import pdb
|
||||
|
||||
pdb.set_trace()
|
||||
|
||||
@@ -6,27 +6,26 @@ from volatility.framework import validity
|
||||
__author__ = 'mike'
|
||||
|
||||
|
||||
class ConfigurationInterface(validity.ValidityRoutines):
|
||||
"""Allows the Configuration components to be composable"""
|
||||
class GenericRequirement(validity.ValidityRoutines, metaclass = ABCMeta):
|
||||
"""Class to handle a single specific configuration option"""
|
||||
|
||||
def __init__(self, name = None):
|
||||
def __init__(self, name, description = None, default = None, optional = False):
|
||||
"""Creates a new option"""
|
||||
validity.ValidityRoutines.__init__(self)
|
||||
self._default = default
|
||||
self._type_check(name, str)
|
||||
self._name = name
|
||||
self._description = description
|
||||
self.value = None
|
||||
self._optional = optional
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
|
||||
class GenericRequirement(ConfigurationInterface, ABCMeta):
|
||||
"""Class to handle a single specific configuration option"""
|
||||
|
||||
def __init__(self, name, description = None, default = None):
|
||||
"""Creates a new option"""
|
||||
ConfigurationInterface.__init__(self, name)
|
||||
self._default = default
|
||||
self._description = description
|
||||
self._value = None
|
||||
@property
|
||||
def optional(self):
|
||||
return self._optional
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@@ -38,12 +37,12 @@ class GenericRequirement(ConfigurationInterface, ABCMeta):
|
||||
"""A short description of what the Option is designed to affect or achieve."""
|
||||
return self._description
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
"""Returns the value of the option, or not if it has not yet been set"""
|
||||
return self._value
|
||||
|
||||
@abstractmethod
|
||||
def set_value(self, value):
|
||||
"""Populates the value doing typing checking/casting in the process"""
|
||||
def check_value(self, value, context):
|
||||
"""Validates the value against a context
|
||||
|
||||
Returns True if the value is valid
|
||||
Throws exceptions if the valid is invalid"""
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -33,15 +33,12 @@ class PluginInterface(validity.ValidityRoutines, metaclass = ABCMeta):
|
||||
return self._context
|
||||
|
||||
@abstractmethod
|
||||
def establish_context(self):
|
||||
"""Alters the context to ensure the plugin can run.
|
||||
def requirements(self):
|
||||
"""Returns a ConfigGroup object to contain the required options"""
|
||||
pass
|
||||
|
||||
This function constructs the necessary symbol spaces that the plugin will need.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def plugin_options(self, config_group = None):
|
||||
"""Modifies the passed in ConfigGroup object to contain the required options"""
|
||||
def check_requirements(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def __call__(self, context):
|
||||
|
||||
Reference in New Issue
Block a user