
    Xf}                     T   d Z ddlZddlZddlZddlZddlZddlZddlZddl	m
Z
mZ ddlmZmZmZmZmZmZmZmZmZmZmZ ddlmZmZ ddlmZmZ dZ	  ej        e           Z!e"e#e$e%fZ&ee"e#e$e%f         Z'eee'ee'         f                  Z(de%fd	Z)d
e%de%fdZ*d
e%de%fdZ+d"de%de"de%fdZ, G d dej	        j-                  Z. G d de
          Z/ G d de/          Z0 G d de/          Z1 G d de/          Z2 G d de/          Z3 G d de
          Z4 G d  d!          Z5dS )#a  The configuration module contains classes and functions for interacting with
the configuration and requirement trees.

Volatility plugins can specify a list of requirements (which may have
subrequirements, thus forming a requirement tree). These requirement
trees can contain values, which are contained in a complementary
configuration tree.  These two trees act as a protocol between the
plugins and users.  The plugins provide requirements that must be
fulfilled, and the users provide configurations values that fulfill
those requirements.  Where the user does not provide sufficient
configuration values, automagic modules may extend the configuration
tree themselves.
    N)ABCMetaabstractmethod)AnyClassVarDict	GeneratorIteratorListOptionalTypeUnionTupleSet)classproperty	framework)	constants
interfaces.returnc                  h    t          d | D                       } t                              |           S )z#Joins configuration paths together.c                     g | ]}||S  r   ).0args     `/home/panchajanya/Development/work/volatility3/volatility3/framework/interfaces/configuration.py
<listcomp>zpath_join.<locals>.<listcomp>8   s    ---#-#---    )tupleCONFIG_SEPARATORjoin)argss    r   	path_joinr"   5   s4     -----..D  &&&r   valuec                 v    t                               |                     t                     dd                   S )z@Returns the parent configuration path from a configuration path.N)r   r    splitr#   s    r   parent_pathr(   <   s,      -=!>!>ss!CDDDr   c                 B    |                      t                    d         S )z(Return the top of the configuration pathr%   )r&   r   r'   s    r   	path_headr*   A   s    ;;'((,,r      pathdepthc                 `    t          |                     t                    d|                   S )zReturns the `path` up to a certain depth.

    Note that `depth` can be negative (such as `-x`) and will return all
    elements except for the last `x` components
    N)r"   r&   r   )r,   r-   s     r   
path_depthr/   F   s(     TZZ 011&5&9:::r   c            	          e Zd ZdZdefdeedf         deddfdZd Ze	defd	            Z
e	defd
            ZdedefdZdedefdZdee         fdZdeeddf         fdZdedefdZdededdfdZd!dedededdfdZdedefdZdeddfdZdedefdZdefdZdedd fdZdedd ddfdZ	 d"dedd deddfdZd#dZ defd Z!dS )$HierarchicalDictz|The core of configuration data, it is a mapping class that stores keys
    within itself, and also stores lower hierarchies.Ninitial_dictSimpleTypeRequirement	separatorr   c                    t          |t                    rt          |          dk    st          d|           || _        i | _        i | _        t          |t                    rt          j        |          }t          |t                    r!|
                                D ]
\  }}|| |<   dS |t          d|           dS )z
        Args:
            initial_dict: A dictionary to populate the HierarchicalDict with initially
            separator: A custom hierarchy separator (defaults to CONFIG_SEPARATOR)
        r+   z*Separator must be a one character string: NzJInitial_dict must be a dictionary or JSON string containing a dictionary: )
isinstancestrlen	TypeError
_separator_data_subdictjsonloadsdictitems)selfr2   r4   kvs        r   __init__zHierarchicalDict.__init__S   s     9c** 	Vs9~~/B/BTTTUUU#24
79lC(( 	4:l33LlD)) 	$**,,  1Q %k]ikk   &%r   c                 B    t          |           t          |          k    S )z)Define equality between HierarchicalDicts)r?   )rA   others     r   __eq__zHierarchicalDict.__eq__l   s    DzzT%[[((r   c                     | j         S )z?Specifies the hierarchy separator in use in this HierarchyDict.)r:   rA   s    r   r4   zHierarchicalDict.separatorp   s     r   c                 4    | j                                         S )zQReturns just the data-containing mappings on this level of the
        Hierarchy.)r;   copyrI   s    r   datazHierarchicalDict.datau   s     z   r   keyc                 \    | j         |v r"|d|                    | j                            S |S )zyReturns the first division of a key based on the dict separator, or
        the full key if the separator is not present.Nr4   indexrA   rM   s     r   	_key_headzHierarchicalDict._key_head{   s5     >S  24>22233Jr   c                 b    | j         |v r%||                    | j                   dz   d         S dS )z|Returns all but the first division of a key based on the dict
        separator, or None if the separator is not in the key.r+   N rO   rQ   s     r   	_key_tailzHierarchicalDict._key_tail   s:     >S  syy00146677rr   c                 *    |                                  S )z?Returns an iterator object that supports the iterator protocol.)	generatorrI   s    r   __iter__zHierarchicalDict.__iter__   s    ~~r   c              #   x   K   | j         D ]}|V  | j        D ]!}| j        |         D ]}|| j        z   |z   V  "dS )zA generator for the data in this level and lower levels of this
        mapping.

        Returns:
            Returns each item in the top level data, and then all subkeys in a depth first order
        N)r;   r<   r4   )rA   rM   subdict_keys      r   rW   zHierarchicalDict.generator   su       : 	 	CIIII= 	9 	9K}[1 9 9!DN2S888889	9 	9r   c                     	 | j         |v r;| j        |                     |                   }||                     |                   S | j        |         S # t
          $ r t          |          w xY w)zJGets an item, traversing down the trees to get to the final
        value.r4   r<   rR   rU   r;   KeyErrorrA   rM   subdicts      r   __getitem__zHierarchicalDict.__getitem__   sv    	 ~$$-s(;(;<t~~c2233z#& 	  	  	 3--	 s   AA A A-r#   c                 2    |                      ||           dS )z@Sets an item or creates a subdict and sets the item within that.N)_setitemrA   rM   r#   s      r   __setitem__zHierarchicalDict.__setitem__   s    c5!!!!!r   Tis_datac                 
   | j         |v r| j                            |                     |          t	          | j                             }|                    |                     |          ||           || j        |                     |          <   dS |r|                     |          | j        |<   dS t          |t                    s/t          d                    t          |                              || j        |<   dS )z9Set an item or appends a whole subtree at a key location.r4   zMHierarchicalDicts can only store HierarchicalDicts within their structure: {}N)r4   r<   getrR   r1   rb   rU   _sanitize_valuer;   r6   r9   formattype)rA   rM   r#   re   r_   s        r   rb   zHierarchicalDict._setitem   s   >S  m''s##%5%O%O%O G T^^C00%AAA18DM$..--... 	+"&"6"6u"="=
3!%)9:: #gnn KK   
 &+c"""r   c                 D   t          |t                    rt          |          S t          |t                    rt          |          S t          |t                    rt          |          S t          |t                    rt	          |          S t          |t
                    rYg }|D ]R}|                     |          }t          |t
                    rt          d          ||                    |           S|S |dS t          dt          |                     )zgMethod to ensure all values are standard values and not volatility
        objects containing contexts.z2Configuration list types cannot contain list typesNz&Invalid type stored in configuration: )
r6   boolintr7   byteslistri   r9   appendrk   )rA   r#   new_listelementelement_values        r   ri   z HierarchicalDict._sanitize_value   s(    eT"" 	T;;s## 	Tu::s## 	Tu::u%% 	T<<t$$ 	TH  3 3 $ 4 4W = =mT22 #L   !,OOM222O]4RT%[[RRSSSr   c                     	 | j         |v r8| j        |                     |                   }||                     |          = dS | j        |                     |          = dS # t
          $ r t          |          w xY w)z+Deletes an item from the hierarchical dict.Nr\   r^   s      r   __delitem__zHierarchicalDict.__delitem__   s    	 ~$$-s(;(;<DNN3//000Jt~~c22333 	  	  	 3--	 s   ?A  A   A:c                     | j         |v rI	 | j        |                     |                   }|                     |          |v S # t          $ r Y dS w xY w|| j        v S )z7Determines whether the key is present in the hierarchy.F)r4   r<   rR   rU   r]   r;   r^   s      r   __contains__zHierarchicalDict.__contains__   st    >S  -s(;(;<~~c**g55   uu $*$$s   6A 
AAc                 h    t          | j                  t          d | j        D                       z   S )z Returns the length of all items.c                 ,    g | ]}t          |          S r   )r8   )r   r_   s     r   r   z,HierarchicalDict.__len__.<locals>.<listcomp>   s    %P%P%Pwc'll%P%P%Pr   )r8   r;   sumr<   rI   s    r   __len__zHierarchicalDict.__len__   s.    4:%P%P$-%P%P%P!Q!QQQr   c                 N   	 | j         |v rF| j        |                     |                                       |                     |                    S | j        |         S # t
          $ r. |                     |t          | j                   d           Y nw xY wt                      S )a  Returns the HierarchicalDict housed under the key.

        This differs from the data property, in that it is directed by the `key`, and all layers under that key are
        returned, not just those in that level.

        Higher layers are not prefixed with the location of earlier layers, so branching a hierarchy containing `a.b.c.d`
        on `a.b` would return a hierarchy containing `c.d`, not `a.b.c.d`.

        Args:
            key: The location within the hierarchy to return higher layers.

        Returns:
            The HierarchicalDict underneath the specified key (not just the data at that key location in the tree)
        rg   F)rM   r#   re   )r4   r<   rR   branchrU   r]   rb   r1   rQ   s     r   r~   zHierarchicalDict.branch   s    	~$$}T^^C%8%89@@PSATATUUU}S)) 	 	 	MM/$.IIISX      	  !!!s   AA A 5BBc                     t          |t                    rt          |t                    st          d          |                     ||d           dS )zSplices an existing HierarchicalDictionary under a specific key.

        This can be thought of as an inverse of :func:`branch`, although
        `branch` does not remove the requested hierarchy, it simply
        returns it.
        7Splice requires a string key and HierarchicalDict valueFN)r6   r7   r1   r9   rb   rc   s      r   splicezHierarchicalDict.splice  sU     #s## 	W:e=M+N+N 	WUVVVc5%(((((r   F	overwritec                 <   t          |t                    rt          |t                    st          d          t	          |          D ]R}|                     || j        z   |z   d          |r||         | || j        z   |z   <   <||         | || j        z   |z   <   SdS )a  Acts similarly to splice, but maintains previous values.

        If overwrite is true, then entries in the new value are used over those that exist within key already

        Args:
            key: The location within the hierarchy at which to merge the `value`
            value: HierarchicalDict to be merged under the key node
            overwrite: A boolean defining whether the value will be overwritten if it already exists
        r   N)r6   r7   r1   r9   r?   rh   r:   )rA   rM   r#   r   items        r   mergezHierarchicalDict.merge  s     #s## 	W:e=M+N+N 	WUVVVKK 	A 	ADxxdo-4d;;G E9>tDt.565:4[S4?*T122	A 	Ar   c                 *    t          j        |           S )zDuplicates the configuration, allowing changes without affecting the
        original.

        Returns:
            A duplicate HierarchicalDict of this object
        )rK   deepcopyrI   s    r   clonezHierarchicalDict.clone.  s     }T"""r   c           	           t          j        t           fdt                                                     D                       d          S )z9Turns the Hierarchical dict into a string representation.c                 $    g | ]}||         fS r   r   )r   rM   rA   s     r   r   z,HierarchicalDict.__str__.<locals>.<listcomp>:  s"    GGGs3S	"GGGr      )indent)r=   dumpsr?   sortedrW   rI   s   `r   __str__zHierarchicalDict.__str__7  sQ    zGGGGfT^^5E5E.F.FGGGHHQR
 
 
 	
r   )T)F)r   r1   )"__name__
__module____qualname____doc__r   r   r7   rD   rG   propertyr4   rL   rR   rU   r	   r   rX   r   rW   ConfigSimpleTyper`   rd   rm   rb   ri   rv   rx   rn   r|   r~   r   r   r   r   r   r   r   r1   r1   O   s        9 9
 <@) 3 778  
	   2) ) ) 3    X !d ! ! ! X!
S S    S S     (3-        99S$_5 9 9 9 9
 s 
 '7 
  
  
  
 "s "3 "4 " " " "+ +C + +d +d + + + +(TS T-= T T T T6	 s 	 t 	  	  	  	 	% 	% 	% 	% 	% 	%R R R R R"# ""4 " " " "4	)# 	)&8 	)T 	) 	) 	) 	) FKA AA1A>BA	A A A A*# # # #
 
 
 
 
 
 
r   r1   c                       e Zd ZdZ	 	 	 ddededededdf
 fd	Zdefd
Zd Z	e
defd            Ze
defd            Ze
defd            Ze
defd            Zej        dd            Z	 ddddededefdZe
deed f         fd            ZddZddZdddedeed f         fdZedddedeed f         fd            Z xZS )RequirementInterfacea  Class that defines a requirement.

    A requirement is a means for plugins and other framework components to request specific configuration data.
    Requirements can either be simple types (such as
    :class:`~volatility3.framework.configuration.requirements.SimpleTypeRequirement`,
    :class:`~volatility3.framework.configuration.requirements.IntRequirement`,
    :class:`~volatility3.framework.configuration.requirements.BytesRequirement` and
    :class:`~volatility3.framework.configuration.requirements.StringRequirement`) or complex types (such
    as :class:`TranslationLayerRequirement`, :class:`SymbolTableRequirement` and :class:`ClassRequirement`
    NFnamedescriptiondefaultoptionalr   c                     t                                                       t          |v rt          dt           d          || _        |pd| _        || _        || _        i | _        dS )a(  

        Args:
            name: The name of the requirement
            description: A short textual description of the requirement
            default: The default value for the requirement if no value is provided
            optional: Whether the requirement must be satisfied or not
        z2Name cannot contain the config-hierarchy divider ()rT   N)	superrD   r   
ValueError_name_description_default	_optional_requirements)rA   r   r   r   r   	__class__s        r   rD   zRequirementInterface.__init__J  sy     	t##XEUXXX   
'-2!>@r   c                 <    d| j         j        z   dz   | j        z   dz   S )N<z: >)r   r   r   rI   s    r   __repr__zRequirementInterface.__repr__d  s#    T^,,t3di?#EEr   c                     t          || j                  sdS | j        D ]/}|j                            |d           | j        |         k    r dS 0dS )NFT)r6   r   __dict__rh   )rA   rF   r   s      r   rG   zRequirementInterface.__eq__g  sb    %00 	5M 	 	D~!!$--t1DDDuu Etr   c                     | j         S )zThe name of the Requirement.

        Names cannot contain CONFIG_SEPARATOR ('.' by default) since
        this is used within the configuration hierarchy.
        )r   rI   s    r   r   zRequirementInterface.nameo  s     zr   c                     | j         S )zUA short description of what the Requirement is designed to affect or
        achieve.)r   rI   s    r   r   z RequirementInterface.descriptionx  s       r   c                     | j         S )z(Returns the default value if one is set.)r   rI   s    r   r   zRequirementInterface.default~  s     }r   c                     | j         S )z+Whether the Requirement is optional or not.)r   rI   s    r   r   zRequirementInterface.optional  s     ~r   c                 .    t          |          | _        dS )z*Sets the optional value for a requirement.N)rm   r   rA   r#   s     r   r   zRequirementInterface.optional  s     er   context#interfaces.context.ContextInterfaceconfig_pathc                 8    |j                             ||          S )aq  Returns the value for this Requirement from its config path.

        Args:
            context: the configuration store to find the value for this requirement
            config_path: the configuration path of the instance of the requirement to be recovered
            default: a default value to provide if the requirement's configuration value is not found
        )configrh   )rA   r   r   r   s       r   config_valuez!RequirementInterface.config_value  s     ~!!+w777r   c                 4    | j                                         S )zLReturns a dictionary of all the child requirements, indexed by
        name.)r   rK   rI   s    r   requirementsz!RequirementInterface.requirements  s     !&&(((r   requirementc                 $    || j         |j        <   dS )zAdds a child to the list of requirements.

        Args:
            requirement: The requirement to add as a child-requirement
        Nr   r   rA   r   s     r   add_requirementz$RequirementInterface.add_requirement  s     0;;+,,,r   c                      | j         |j        = dS )zRemoves a child from the list of requirements.

        Args:
            requirement: The requirement to remove as a child-requirement
        Nr   r   s     r   remove_requirementz'RequirementInterface.remove_requirement  s     {/000r   c                     i }| j                                         D ]G}|j        s>|                    |t	          || j                            }|                    |           H|S )ac  Method that will validate all child requirements.

        Args:
            context: the context containing the configuration data for this requirement
            config_path: the configuration path of this instance of the requirement

        Returns:
            A dictionary of full configuration paths for each unsatisfied child-requirement
        )r   valuesr   unsatisfiedr"   r   update)rA   r   r   resultr   	subresults         r   unsatisfied_childrenz)RequirementInterface.unsatisfied_children  sr     ,3355 	) 	)K' )'33Y{DJ?? 	 i(((r   c                     dS )a  Method to validate the value stored at config_path for the
        configuration object against a context.

        Returns a list containing its own name (or multiple unsatisfied requirement names) when invalid

        Args:
            context: The context object containing the configuration for this requirement
            config_path: The configuration path for this requirement to test satisfaction

        Returns:
            A dictionary of configuration-paths to requirements that could not be satisfied
        Nr   rA   r   r   s      r   r   z RequirementInterface.unsatisfied        r   )NNFr   NN)r   r   r   N)r   r   r   r   r7   r   rm   rD   r   rG   r   r   r   r   r   setterr   r   r   r   r   r   r   r   __classcell__r   s   @r   r   r   >  s       	 	  $(A AA A "	A
 A 
A A A A A A4F# F F F F   c    X !S ! ! ! X!
 )    X $    X _% % % _% %)	8 868 8 "	8
 
8 8 8 8  )d3(>#>? ) ) ) X)
; ; ; ;1 1 1 1<KN	c))	*   , <KN	c))	*   ^    r   r   )	metaclassc                   j    e Zd ZU dZeZee         ed<   de	fdZ
de	fdZddded	eee	f         fd
ZdS )r3   zjClass to represent a single simple type (such as a boolean, a string, an
    integer or a series of bytes)instance_typer   c                      t          d          zPAlways raises a TypeError as instance requirements cannot have
        children.z1Instance Requirements cannot have subrequirementsr9   r   s     r   r   z%SimpleTypeRequirement.add_requirement       KLLLr   c                      t          d          r   r   r   s     r   r   z(SimpleTypeRequirement.remove_requirement  r   r   r   r   r   r   c           
      <   t          || j                  }|                     ||d          }t          || j                  sZt
                              t          j        d	                    | j        | j        j
        t          |                               || iS i S )zJValidates the instance requirement based upon its
        `instance_type`.Nz3TypeError - {} requirements only accept {} type: {})r"   r   r   r6   r   volloglogr   
LOGLEVEL_Vrj   r   reprrA   r   r   r#   s       r   r   z!SimpleTypeRequirement.unsatisfied  s    
  TY77!!';==%!344 	'JJ$ELLIt1:DKK     &&	r   N)r   r   r   r   rm   r   r   r   __annotations__r   r   r   r7   r   r   r   r   r   r3   r3     s         % % %)M8D>(((M+? M M M M
M.B M M M M
<KN	c''	(     r   r3   c                   z     e Zd ZdZd fdZ fdZedee         fd            Z	ddd	e
dee
ef         fd
Z xZS )ClassRequirementzRequires a specific class.

    This is used as means to serialize specific classes for
    :class:`TranslationLayerRequirement` and
    :class:`SymbolTableRequirement` classes.
    r   Nc                 H     t                      j        |i | d | _        d S r   )r   rD   _clsrA   r!   kwargsr   s      r   rD   zClassRequirement.__init__  s*    $)&)))			r   c                 F    t                                          |          S r   r   rG   rA   rF   r   s     r   rG   zClassRequirement.__eq__
       ww~~e$$$r   c                     | j         S )zWContains the actual chosen class based on the configuration value's
        class name.)r   rI   s    r   clszClassRequirement.cls  s     yr   r   r   r   c                    t          || j                  }|                     ||d          }d| _        |t	          |t
                    rd|v rt          j                            |d|	                    d                   d          }||	                    d          dz   d         }t          ||          rt          ||          | _        n)|t                      v rt                      |         | _        | j        || iS i S )z*Checks to see if a class can be recovered.Nr   r+   )r"   r   r   r   r6   r7   sysmodulesrh   rindexhasattrgetattrglobals)rA   r   r   r#   module
class_names         r   r   zClassRequirement.unsatisfied  s      TY77!!';==	E3!7!7e||/Bc1B1B/B)CTJJ"5<<#4#4q#8#:#:;
6:.. < '
 ; ;DIGII%% '		% 0DI9&&	r   r   )r   r   r   r   rD   rG   r   r   r   r   r7   r   r   r   r   r   s   @r   r   r     s              % % % % %
 Xd^    X
<KN	c''	(       r   r   c            
            e Zd ZdZd fdZ fdZedddeddfd	            Zdddeddfd
Z		 ddddede
eef         ded         fdZ xZS )!ConstructableRequirementInterfacea  Defines a Requirement that can be constructed based on their own
    requirements.

    This effectively offers a means for serializing specific python
    types, to be reconstructed based on simple configuration data.  Each
    constructable records a `class` requirement, which indicates the
    object that will be constructed.  That class may have its own
    requirements (which is why validation of a ConstructableRequirement
    must happen after the class configuration value has been provided).
    These values are then provided to the object's constructor by name
    as arguments (as well as the standard `context` and `config_path`
    arguments).
    r   Nc                      t                      j        |i | |                     t          dd                     t	                      | _        d S )Nclassz&Class of the constructable requirement)r   rD   r   r   set_current_class_requirementsr   s      r   rD   z*ConstructableRequirementInterface.__init__;  sY    $)&)))W&NOO	
 	
 	
 69UU(((r   c                 F    t                                          |          S r   r   r   s     r   rG   z(ConstructableRequirementInterface.__eq__B  r   r   r   r   r   c                     dS )a6  Method for constructing within the context any required elements
        from subrequirements.

        Args:
            context: The context object containing the configuration data for the constructable
            config_path: The configuration path for the specific instance of this constructable
        Nr   r   s      r   	constructz+ConstructableRequirementInterface.constructG  r   r   c                    | j         d         }t          || j                  }|                    ||          st	          |t
                    rt          |j        t                    r| j	        
                                D ]$}| j        |= | j	                            |           %|j                                        D ]<}| j	                            |j                   |                     |           7dS dS dS dS )a|  Method to check if the class Requirement is valid and if so populate
        the other requirements (but no need to validate, since we're invalid
        already)

        Args:
             context: The context object containing the configuration data for the constructable
             config_path: The configuration path for the specific instance of this constructable
        r   N)r   r"   r   r   r6   r   
issubclassr   ConfigurableInterfacer   rK   r   removeget_requirementsaddr   )rA   r   r   	class_reqsubreq_config_pathold_reqr   s          r   _validate_classz1ConstructableRequirementInterface._validate_classS  s'    %g.	&{DI>>$$W.@AA 	6j'G
 G
 	6 )-)>?? 6#?DDFF E EG*734;;GDDDD#,=#A#A#C#C 6 6K4889IJJJ((5555	6 	6 	6 	66 66 6r   requirement_dictz"interfaces.objects.ObjectInterfacec                     | j         d                             ||          rdS t          | j         d         t                    sdS | j         d         j        }|dS |i } |di |}|j        |j        |<   |S )z\Constructs the class, handing args and the subrequirements as
        parameters to __init__r   Nr   )r   r   r6   r   r   r   r   )rA   r   r   r  r   objs         r   _construct_classz2ConstructableRequirementInterface._construct_classn  s     W%11';GG 	4$+G46FGG 	4(,;4 #! c%%$%%&)h{#
r   r   r   )r   r   r   r   rD   rG   r   r7   r   r  r   objectr   r
  r   r   s   @r   r   r   ,  s        ; ; ; ; ; ;% % % % %
 	<	KN			 	 	 ^	6<6KN6	6 6 6 6> /3	   6    sF{+	 
 
6	7               r   r   c                   *    e Zd ZdZdddededefdZdS )	 ConfigurableRequirementInterfacez7Simple Abstract class to provide build_required_config.r   r   r   r#   r   c                     dS )z0Proxies to a ConfigurableInterface if necessary.Nr   r   s       r   build_configurationz4ConfigurableRequirementInterface.build_configuration  r   r   N)r   r   r   r   r7   r   r1   r  r   r   r   r  r    sT        AA?6? ? 	?
 
? ? ? ? ? ?r   r  c            	       6    e Zd ZdZdddeddf fdZedd            Zedefd	            Zej	        d
eddfd            Zede
fd            Zde
fdZedee         fd            Zedddedeeef         fd            Zedddedefd            Z xZS )r   ziClass to allow objects to have requirements and read configuration data
    from the context config tree.r   r   r   r   Nc                 r    t                                                       || _        || _        d| _        dS )zXBasic initializer that allows configurables to access their own
        config settings.N)r   rD   _context_config_path_config_cache)rA   r   r   r   s      r   rD   zConfigurableInterface.__init__  s8    
 	'9=r   c                     | j         S )zXThe context object that this configurable belongs to/configuration
        is stored in.)r  rI   s    r   r   zConfigurableInterface.context  s     }r   c                     | j         S )8The configuration path on which this configurable lives.)r  rI   s    r   r   z!ConfigurableInterface.config_path  s       r   r#   c                 "    || _         d| _        dS )r  N)r  r  r   s     r   r   z!ConfigurableInterface.config_path  s     "!r   c                     t          | d          r| j        )| j        j                            | j                  | _        | j        S )zOThe Hierarchical configuration Dictionary for this Configurable
        object.r  )r   r  r  r   r~   r  rI   s    r   r   zConfigurableInterface.config  sF     t_-- 	P1C1K!%!5!<!<T=N!O!OD!!r   c           	      t   t                      }|                                 D ]}| j                            |j        d          }|t          |t                    s
|||j        <   t          |t                    r<|:|                    |j        |	                    | j
        | j        |                     |S )ae  Constructs a HierarchicalDictionary of all the options required to
        build this component in the current context.

        Ensures that if the class has been created, it can be recreated
        using the configuration built Inheriting classes must override
        this to ensure any dependent classes update their configurations
        too
        N)r1   r  r   rh   r   r6   r   r  r   r  r   r   )rA   r   reqr#   s       r   r  z)ConfigurableInterface.build_configuration  s     "##((** 	 	CKOOCHd33E 6* *  $)sx #?@@ $MM//d>NPUVV   r   c                     g S )zOReturns a list of RequirementInterface objects required by this
        object.r   r   s    r   r  z&ConfigurableInterface.get_requirements  s	     	r   c                     i }|                                  D ]4}|j        s+|                    ||          }|                    |           5|S )ar  Returns a list of the names of all unsatisfied requirements.

        Since a satisfied set of requirements will return [], it can be used in tests as follows:

        .. code-block:: python

            unmet = configurable.unsatisfied(context, config_path)
            if unmet:
                raise RuntimeError("Unsatisfied requirements: {}".format(unmet)
        )r  r   r   r   )r   r   r   r   r   r   s         r   r   z!ConfigurableInterface.unsatisfied  s\     //11 	) 	)K' )'33G[II	i(((r   base_config_pathc           	      \   d                     d t          d          D                       }t          ||          }|                                D ]Z\  }}t	          |t
          t          t          t          t          f          st          d          ||j        t          ||          <   [|S )a  Convenience function to allow constructing a new randomly generated
        sub-configuration path, containing each element from kwargs.

        Args:
            context: The context in which to store the new configuration
            base_config_path: The base configuration path on which to build the new configuration
            kwargs: Keyword arguments that are used to populate the new configuration path

        Returns:
            str: The newly generated full configuration path
        rT   c              3      K   | ]A}t          j                                        t          j        t          j        z             V  Bd S r   )randomSystemRandomchoicestringascii_uppercasedigits)r   _s     r   	<genexpr>z7ConfigurableInterface.make_subconfig.<locals>.<genexpr>
  sW       %
 %
 !!(()?&-)OPP%
 %
 %
 %
 %
 %
r      z?Config values passed to make_subconfig can only be simple types)r    ranger"   r@   r6   rn   r7   rm   floatro   r9   r   )r   r   r  r   random_config_dictnew_config_pathrB   rC   s           r   make_subconfigz$ConfigurableInterface.make_subconfig  s    $  WW %
 %
1XX%
 %
 %
 
 
 $$46HII LLNN 	> 	>DAqa#sD%!?@@ U   =>GN9_a8899r   )r   r   )r   r   r   r   r7   rD   r   r   r   r   r1   r   r  classmethodr
   r   r  r   r   r/  r   r   s   @r   r   r     s       % %><>KN>	> > > > > >    X
 !S ! ! ! X! " " " " " "
 "( " " " X"%5    2 &:!;    [
 ;JM	c''	(   [( "6" "
 
" " " [" " " " "r   r   c                        e Zd ZU dZdZeeeef         ed<   dZeeeef         ed<    fdZ	e
deeeef         fd            Z xZS )VersionableInterfacea  A class that allows version checking so that plugins can request specific versions of components they made need

    This currently includes other Plugins and scanners, but may be extended in the future

    All version number should use semantic versioning
    )r   r   r   _version_required_framework_versionc                 `    t          j        | j           t                      j        |i | d S r   )r   require_interface_versionr4  r   rD   r   s      r   rD   zVersionableInterface.__init__)  s6    +T-MNN$)&)))))r   r   c                     | j         S )a  The version of the current interface (classmethods available on the component).

        It is strongly recommended that Semantic Versioning be used (and the default version verification is defined that way):

            MAJOR version when you make incompatible API changes.
            MINOR version when you add functionality in a backwards compatible manner.
            PATCH version when you make backwards compatible bug fixes.
        )r3  r  s    r   versionzVersionableInterface.version-  s     |r   )r   r   r   r   r3  r   rn   r   r4  rD   r   r8  r   r   s   @r   r2  r2    s           &/HeCcM"...8AsC}!5AAA* * * * * 	c3m, 	 	 	 ]	 	 	 	 	r   r2  )r+   )6r   collections.abccollectionsrK   r=   loggingr"  r%  r   abcr   r   typingr   r   r   r   r	   r
   r   r   r   r   r   volatility3r   r   volatility3.frameworkr   r   r   	getLoggerr   r   rn   rm   ro   r7   
BasicTypesSimpleTypesr   r"   r(   r*   r/   Mappingr1   r   r3   r   r   r  r   r2  r   r   r   <module>rD     s             



 ' ' ' ' ' ' ' '                          1 0 0 0 0 0 0 0 7 7 7 7 7 7 7 7  D		8	$	$4$
Cuc)*E+tK/@"@AB ' ' ' ' 'Es Es E E E E
-S -S - - - -
; ;S ; ;S ; ; ; ;l
 l
 l
 l
 l
{. l
 l
 l
^Z Z Z Z ZW Z Z Z Zz         0      F+ + + + ++ + + +\b b b b b(< b b bJ	? 	? 	? 	? 	?'; 	? 	? 	?~ ~ ~ ~ ~g ~ ~ ~ ~B         r   