Source code for plaso.filters.expressions

"""The event filter expression parser expression classes."""

import abc

from dfdatetime import interface as dfdatetime_interface

from plaso.filters import filters
from plaso.filters import logger
from plaso.filters import value_types
from plaso.lib import errors


[docs] class Expression: """An event filter parser expression. Attributes: attribute (str): attribute or None if not set. args (list[object]): arguments. number_of_args (int): expected number of arguments. operator (str): operator or None if not set. """ # TODO: this currently needs to be a class attribute for objectfilter. # See if this can be changed to an instance attribute. attribute = None
[docs] def __init__(self): """Initializes an event filter parser expression.""" super().__init__() self.attribute = None self.args = [] self.number_of_args = 1 self.operator = None
[docs] def AddArgument(self, argument): """Adds a new argument to this expression. Args: argument (object): argument to add. Returns: bool: True if the argument is the last argument, False otherwise. Raises: ParseError: If there are too many arguments. """ self.args.append(argument) if len(self.args) > self.number_of_args: raise errors.ParseError("Too many arguments for this expression.") if len(self.args) == self.number_of_args: return True return False
[docs] @abc.abstractmethod def Compile(self): """Compiles the expression into a filter. Returns: Filter: filter object corresponding the expression. """
[docs] def SetAttribute(self, attribute): """Sets the attribute. Args: attribute (str): attribute, or None if not set. """ self.attribute = attribute
[docs] def SetOperator(self, operator): """Set the operator. Args: operator (str): operator, such as "and" or "&&", or None if not set. """ self.operator = operator
[docs] class BinaryExpression(Expression): """An event filter parser expression which takes two other expressions."""
[docs] def __init__(self, operator=""): """Initializes an event filter parser binary expression. Args: operator (str): operator, such as "and" or "&&". """ super().__init__() self.args = [] self.operator = operator
[docs] def __repr__(self): """Retrieves a string representation of the object for debugging.""" if len(self.args) == 2: return f"({self.args[0]!s}) {self.operator:s} {self.args[1]!s}" return self.operator
[docs] def AddOperands(self, lhs, rhs): """Adds an operand. Args: lhs (Expression): left hand side expression. rhs (Expression): right hand side expression. Raises: ParseError: if either left hand side or right hand side expression is not an instance of Expression. """ # TODO: add information about what lhs and rhs are to these error messages. # https://github.com/log2timeline/plaso/pull/2498 if not isinstance(lhs, Expression): raise errors.ParseError("Left hand side is not an expression") if not isinstance(rhs, Expression): raise errors.ParseError("Right hand side is not an expression") self.args = [lhs, rhs]
[docs] def Compile(self): """Compiles the expression into a filter. Returns: Filter: filter object corresponding the expression. Raises: ParseError: if the operator is not supported. """ operator = self.operator.lower() if operator in ("and", "&&"): filter_class = filters.AndFilter elif operator in ("or", "||"): filter_class = filters.OrFilter else: raise errors.ParseError(f"Unusupported operator: {operator:s}.") args = [argument.Compile() for argument in self.args] return filter_class(arguments=args)
[docs] class IdentityExpression(Expression): """An event filter parser expression which always evaluates to True."""
[docs] def Compile(self): """Compiles the expression into a filter. Returns: IdentityFilter: filter object which always evaluates to True. """ return filters.IdentityFilter()
[docs] class EventExpression(Expression): """Event expression.""" # TODO: add an IsOperator _OPERATORS = { "==": filters.EqualsOperator, ">": filters.GreaterThanOperator, ">=": filters.GreaterEqualOperator, "<": filters.LessThanOperator, "<=": filters.LessEqualOperator, "!=": filters.NotEqualsOperator, "contains": filters.Contains, "equals": filters.EqualsOperator, "inset": filters.InSet, "iregexp": filters.RegexpInsensitive, "is": filters.EqualsOperator, "regexp": filters.Regexp, } _EVENT_FILTER_ALIAS = { "date": "timestamp", "datetime": "timestamp", "time": "timestamp", } _DEPRECATED_EVENT_FILTER_ALIAS = frozenset( ["description_long", "description", "description_short"] )
[docs] def __init__(self): """Initializes an event expression.""" super().__init__() self._bool_value = True
[docs] def __repr__(self): """Retrieves a string representation of the object for debugging.""" return f"{self.attribute:s} {self.operator:s} {self.args!s}"
[docs] def Compile(self): """Compiles the expression into a filter. Returns: Filter: filter object corresponding the expression. Raises: ParseError: if the operator is missing or unknown. """ if self.attribute in self._DEPRECATED_EVENT_FILTER_ALIAS: logger.warning( f'Event filter alias: "{self.attribute:s}" no longer supported' ) if not self.operator: raise errors.ParseError("Missing operator.") lookup_key = self.operator.lower() operator = self._OPERATORS.get(lookup_key) if not operator: raise errors.ParseError(f"Unknown operator: {self.operator:s}.") self.attribute = self._EVENT_FILTER_ALIAS.get(self.attribute, self.attribute) # Convert date and time values to (dfdatetime) date time objects. if self.attribute == "timestamp": date_time_arguments = [] for argument in self.args: if isinstance(argument, dfdatetime_interface.DateTimeValues): date_time = argument else: logger.warning( "Implicit event filter date and time conversion is deprecated " "use the DATETIME() value type indicator instead" ) try: date_time = value_types.DateTimeValueType(argument) except ValueError as exception: raise errors.ParseError(exception) date_time_arguments.append(date_time) self.args = date_time_arguments arguments = [self.attribute] arguments.extend(self.args) ops = operator(arguments=arguments) if not self._bool_value: if hasattr(ops, "FlipBool"): ops.FlipBool() return ops
[docs] def Negate(self): """Reverses the logic of (negates) the expression.""" self._bool_value = not self._bool_value