Source code for dfvfs.analyzer.specification
# -*- coding: utf-8 -*-
"""The format specification classes."""
[docs]
class Signature(object):
"""Signature of a format specification.
The signature consists of a byte string pattern, an optional
offset relative to the start of the data, and a value to indicate
if the pattern is bound to the offset.
Attributes:
identifier (str): unique signature identifier for a specification store.
offset (int): offset of the signature, where None indicates the signature
has no offset. A positive offset or 0 is relative to the start of
the data a negative offset is relative to the end of the data.
pattern (bytes): pattern of the signature.
"""
[docs]
def __init__(self, pattern, offset=None):
"""Initializes a signature.
Args:
pattern (bytes): pattern of the signature. Wildcards or regular pattern
(regexp) are not supported.
offset (Optional[int]): offset of the signature, where None indicates
the signature has no offset. A positive offset or 0 is relative
from the start of the data a negative offset is relative to
the end of the data.
"""
super(Signature, self).__init__()
self.identifier = None
self.offset = offset
self.pattern = pattern
[docs]
def SetIdentifier(self, identifier):
"""Sets the identifier of the signature in the specification store.
Args:
identifier (str): unique signature identifier for a specification store.
"""
self.identifier = identifier
[docs]
class FormatSpecification(object):
"""Format specification."""
[docs]
def __init__(self, identifier):
"""Initializes a specification.
Args:
identifier (str): unique name for the format.
"""
super(FormatSpecification, self).__init__()
self.identifier = identifier
self.signatures = []
[docs]
def AddNewSignature(self, pattern, offset=None):
"""Adds a signature.
Args:
pattern (bytes): pattern of the signature. Wildcards or regular pattern
(regexp) are not supported.
offset (Optional[int]): offset of the signature, where None indicates
the signature has no offset. A positive offset or 0 is relative
from the start of the data a negative offset is relative to
the end of the data.
"""
self.signatures.append(Signature(pattern, offset=offset))
[docs]
class FormatSpecificationStore(object):
"""Store for format specifications."""
[docs]
def __init__(self):
"""Initializes a format specification store."""
super(FormatSpecificationStore, self).__init__()
self._format_specifications = {}
# Maps signature identifiers to format specifications.
self._signature_map = {}
@property
def specifications(self):
"""Retrieves the format specifications.
Returns:
generator[FormatSpecification]: format specifications.
"""
return iter(self._format_specifications.values())
[docs]
def AddNewSpecification(self, identifier):
"""Adds a new format specification.
Args:
identifier (str): unique signature identifier for a specification store.
Returns:
FormatSpecification: format specification.
Raises:
KeyError: if the store already contains a specification with
the same identifier.
"""
if identifier in self._format_specifications:
raise KeyError(
f'Format specification {identifier:s} is already defined in store.')
self._format_specifications[identifier] = FormatSpecification(identifier)
return self._format_specifications[identifier]
[docs]
def AddSpecification(self, specification):
"""Adds a specification.
Args:
specification (FormatSpecification): format specification.
Raises:
KeyError: if the store already contains a specification with
the same identifier.
"""
if specification.identifier in self._format_specifications:
raise KeyError((
f'Format specification {specification.identifier:s} is already '
f'defined in store.'))
self._format_specifications[specification.identifier] = specification
for signature in specification.signatures:
signature_index = len(self._signature_map)
signature_identifier = f'{specification.identifier:s}:{signature_index:d}'
if signature_identifier in self._signature_map:
raise KeyError(
f'Signature {signature_identifier:s} is already defined in map.')
signature.SetIdentifier(signature_identifier)
self._signature_map[signature_identifier] = specification
[docs]
def GetSpecificationBySignature(self, signature_identifier):
"""Retrieves a specification mapped to a signature identifier.
Args:
signature_identifier (str): unique signature identifier for
a specification store.
Returns:
FormatSpecification: A format specification or None if the signature
identifier does not exist within the specification store.
"""
return self._signature_map.get(signature_identifier, None)