Source code for plaso.parsers.text_plugins.viminfo

# -*- coding: utf-8 -*-
"""Text parser plugin for viminfo files."""

import pyparsing

from dfdatetime import posix_time as dfdatetime_posix_time

from plaso.containers import events
from plaso.lib import errors
from plaso.parsers import text_parser
from plaso.parsers.text_plugins import interface


[docs] class VimInfoEventData(events.EventData): """VimInfo event data. Attributes: filename (str): the name of the file that was opened/edited. history_type (str): the Vim history type. history_value (str): the Vim history value. item_number (int): the item number of the history type. recorded_time (dfdatetime.DateTimeValues): date and time the log entry was recorded. """ DATA_TYPE = 'viminfo:history'
[docs] def __init__(self): """Initializes event data.""" super(VimInfoEventData, self).__init__(data_type=self.DATA_TYPE) self.filename = None self.history_type = None self.history_value = None self.item_number = None self.recorded_time = None
[docs] class VimInfoTextPlugin(interface.TextPlugin,): """Parses events from Viminfo files.""" NAME = 'viminfo' DATA_FORMAT = 'Viminfo file' ENCODING = 'utf-8' _FILENAME = '.viminfo' _INTEGER = pyparsing.Word(pyparsing.nums).set_parse_action( lambda tokens: int(tokens[0], 10)) _END_OF_LINE = pyparsing.Suppress(pyparsing.LineEnd()) _HEADER_1 = ( pyparsing.Literal('# This viminfo file was generated by Vim ') + pyparsing.Word(pyparsing.nums + '.') + _END_OF_LINE) _HEADER_2 = ( pyparsing.Literal('# You may edit it if ') + ( pyparsing.Literal('you\'re careful!') ^ pyparsing.Literal('you are careful!')) + _END_OF_LINE) _VERSION_HEADER = ( pyparsing.Literal('# Viminfo version') + _END_OF_LINE) _VERSION_VALUE = ( pyparsing.Literal('|') + pyparsing.Word(pyparsing.nums + ',').set_results_name('version') + _END_OF_LINE) _ENCODING_HEADER = ( pyparsing.Literal('# Value of \'encoding\' when this file was written') + _END_OF_LINE) _ENCODING_VALUE = ( pyparsing.Literal('*') + pyparsing.Literal('encoding=') + pyparsing.Word(pyparsing.alphanums + '-').set_results_name('encoding') + _END_OF_LINE) _PREAMBLE = ( _HEADER_1 + _HEADER_2 + _VERSION_HEADER + _VERSION_VALUE + _ENCODING_HEADER + _ENCODING_VALUE) _HLSEARCH = ( pyparsing.Literal('# hlsearch on (H) or off (h):') + _END_OF_LINE + pyparsing.Word('~/hH').set_results_name('hlsearch') + _END_OF_LINE) # TODO: https://github.com/vim/vim/blob/master/src/viminfo.c#L1525 _SEARCH_PATTERN = ( pyparsing.Literal('# Last Search Pattern:') + _END_OF_LINE + pyparsing.restOfLine().set_results_name('search_pattern') + _END_OF_LINE + _END_OF_LINE) # TODO: https://github.com/vim/vim/blob/master/src/viminfo.c#L1525 _SUBSTITUTE_SEARCH_PATTERN = ( pyparsing.Literal('# Last Substitute Search Pattern:') + _END_OF_LINE + pyparsing.restOfLine().set_results_name('substitute_search_pattern') + _END_OF_LINE + _END_OF_LINE) _SUBSTITUTE_STRING = ( pyparsing.Literal('# Last Substitute String:') + _END_OF_LINE + pyparsing.restOfLine().set_results_name('last_substitute_string') + _END_OF_LINE + _END_OF_LINE) _BAR_ITEM = ( pyparsing.Literal('|') + pyparsing.Word(pyparsing.nums, exact=1) + pyparsing.Suppress(',') + pyparsing.Word(pyparsing.nums, exact=1) + pyparsing.Suppress(',') + pyparsing.Word(pyparsing.nums, exact=10) + pyparsing.Suppress(',') + pyparsing.Optional(_INTEGER) + pyparsing.Suppress(',') + pyparsing.restOfLine() + _END_OF_LINE) _REGISTER_CONTINUATION = ( pyparsing.Literal('|<"') + pyparsing.restOfLine() + _END_OF_LINE) _REGISTER_ITEM = ( pyparsing.Literal('|') + _INTEGER + pyparsing.Suppress(',') + _INTEGER + pyparsing.Suppress(',') + _INTEGER + pyparsing.Suppress(',') + _INTEGER + pyparsing.Suppress(',') + _INTEGER + pyparsing.Suppress(',') + _INTEGER + pyparsing.Suppress(',') + pyparsing.Word(pyparsing.nums, exact=10) + pyparsing.Suppress(',') + pyparsing.Group( pyparsing.restOfLine() + _END_OF_LINE + pyparsing.ZeroOrMore(_REGISTER_CONTINUATION))) _FILEMARK_ITEM = pyparsing.Group( pyparsing.Literal('|') + _INTEGER + pyparsing.Suppress(',') + _INTEGER + pyparsing.Suppress(',') + _INTEGER + pyparsing.Suppress(',') + _INTEGER + pyparsing.Suppress(',') + pyparsing.Word(pyparsing.nums, exact=10) + pyparsing.Suppress(',') + pyparsing.restOfLine() + _END_OF_LINE) _COMMAND_LINE_ITEM = pyparsing.Group( pyparsing.Literal(':') + pyparsing.restOfLine() + _END_OF_LINE + _BAR_ITEM).set_results_name('command_line_items*') _COMMAND_LINE_HISTORY = ( pyparsing.Literal('# Command Line History (newest to oldest):') + _END_OF_LINE + pyparsing.ZeroOrMore(_COMMAND_LINE_ITEM) + _END_OF_LINE) _SEARCH_STRING_ITEM = pyparsing.Group( pyparsing.Literal('?') + pyparsing.restOfLine() + _END_OF_LINE + _BAR_ITEM).set_results_name('search_string_items*') _SEARCH_STRING_HISTORY = ( pyparsing.Literal('# Search String History (newest to oldest):') + _END_OF_LINE + pyparsing.ZeroOrMore(_SEARCH_STRING_ITEM) + _END_OF_LINE) _EXPRESSION_ITEM = pyparsing.Group( pyparsing.Literal('=') + pyparsing.Word(pyparsing.alphas + '/:') + _END_OF_LINE + _BAR_ITEM).set_results_name('expression_history_items*') _EXPRESSION_HISTORY = ( pyparsing.Literal('# Expression History (newest to oldest):') + _END_OF_LINE + pyparsing.ZeroOrMore(_EXPRESSION_ITEM)) _INPUT_LINE_ITEM = pyparsing.Group( pyparsing.Literal('@') + pyparsing.Word(pyparsing.alphas + '/:') + _END_OF_LINE + _BAR_ITEM).set_results_name('input_line_history_items*') _INPUT_LINE_HISTORY = ( pyparsing.Literal('# Input Line History (newest to oldest):') + _END_OF_LINE + pyparsing.ZeroOrMore(_INPUT_LINE_ITEM)) _DEBUG_LINE_ITEM = pyparsing.Group( pyparsing.Literal('@') + pyparsing.Word(pyparsing.alphas + '/:') + _END_OF_LINE + _BAR_ITEM).set_results_name('debug_line_history_items*') _DEBUG_LINE_HISTORY = ( pyparsing.Literal('# Debug Line History (newest to oldest):') + _END_OF_LINE + pyparsing.ZeroOrMore(_DEBUG_LINE_ITEM)) _REGISTERS_CONTENT = ( pyparsing.Suppress(pyparsing.White('\t')) + pyparsing.restOfLine() + _END_OF_LINE) # http://vimdoc.sourceforge.net/htmldoc/change.html#registers _REGISTERS_ITEM = pyparsing.Group( pyparsing.Literal('"') + pyparsing.Or([_INTEGER, pyparsing.Word(pyparsing.printables)]) + pyparsing.Suppress(pyparsing.White('\t')) + pyparsing.one_of(['BLOCK', 'CHAR', 'LINE']) + pyparsing.Suppress(pyparsing.White('\t')) + _INTEGER + _END_OF_LINE + pyparsing.Group(pyparsing.ZeroOrMore(_REGISTERS_CONTENT)) + _REGISTER_ITEM).set_results_name('registers_items*') _REGISTERS_HISTORY = ( pyparsing.Literal('# Registers:') + _END_OF_LINE + pyparsing.ZeroOrMore(_REGISTERS_ITEM)) _FILEMARKS_ITEM = pyparsing.Group( pyparsing.Literal('\'') + _INTEGER + _INTEGER + _INTEGER + pyparsing.restOfLine() + _END_OF_LINE + _FILEMARK_ITEM).set_results_name('filemarks_items*') _FILEMARKS_HISTORY = ( pyparsing.Literal('# File marks:') + _END_OF_LINE + pyparsing.ZeroOrMore(_FILEMARKS_ITEM) + _END_OF_LINE) _JUMPLIST_ITEM = pyparsing.Group( pyparsing.Word('-\'') + _INTEGER + _INTEGER + pyparsing.restOfLine() + _END_OF_LINE + _FILEMARK_ITEM).set_results_name('jumplist_items*') _JUMPLIST_HISTORY = ( pyparsing.Literal('# Jumplist (newest first):') + _END_OF_LINE + pyparsing.ZeroOrMore(_JUMPLIST_ITEM) + _END_OF_LINE) _HISTORY_MARKS_HISTORY = ( pyparsing.Literal('# History of marks within files (newest to oldest):') + _END_OF_LINE) _LINE_STRUCTURES = [ ('command_line_history', _COMMAND_LINE_HISTORY), ('debug_line_history', _DEBUG_LINE_HISTORY), ('expression_history', _EXPRESSION_HISTORY), ('filemarks_history', _FILEMARKS_HISTORY), ('history_marks_history', _HISTORY_MARKS_HISTORY), ('hlsearch', _HLSEARCH), ('input_line_history', _INPUT_LINE_HISTORY), ('jumplist_history', _JUMPLIST_HISTORY), ('preamble', _PREAMBLE), ('registers_history', _REGISTERS_HISTORY), ('search_pattern', _SEARCH_PATTERN), ('search_string_history', _SEARCH_STRING_HISTORY), ('substitute_search', _SUBSTITUTE_SEARCH_PATTERN), ('substitute_string', _SUBSTITUTE_STRING)] VERIFICATION_GRAMMAR = _PREAMBLE def _ParseCommandLineHistory(self, parser_mediator, structure): """Parses command line history items and creates VimInfoEventData objects. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. structure (pyparsing.ParseResults): structure of tokens derived from lines of text that match a command line history """ for index, item in enumerate(structure.get('command_line_items', [])): event_data = VimInfoEventData() event_data.history_value = item[1] event_data.history_type = 'Command Line History' event_data.item_number = index event_data.recorded_time = dfdatetime_posix_time.PosixTime( timestamp=item[5]) parser_mediator.ProduceEventData(event_data) def _ParseSearchStringHistory(self, parser_mediator, structure): """Parses search string history items and creates VimInfoEventData objects. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. structure (pyparsing.ParseResults): structure of tokens derived from lines of text that match a search string history """ for index, item in enumerate(structure.get('search_string_items', [])): event_data = VimInfoEventData() event_data.history_value = item[1] event_data.history_type = 'Search String History' event_data.item_number = index event_data.recorded_time = dfdatetime_posix_time.PosixTime( timestamp=item[5]) parser_mediator.ProduceEventData(event_data) def _ParseExpressionHistory(self, parser_mediator, structure): """Parses expression history items and creates VimInfoEventData objects. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. structure (pyparsing.ParseResults): structure of tokens derived from lines of text that match an expression history """ for index, item in enumerate(structure.get('expression_history_items', [])): event_data = VimInfoEventData() event_data.history_value = item[1] event_data.history_type = 'Expression History' event_data.item_number = index event_data.recorded_time = dfdatetime_posix_time.PosixTime( timestamp=item[5]) parser_mediator.ProduceEventData(event_data) def _ParseInputLineHistory(self, parser_mediator, structure): """Parses input line history items and creates VimInfoEventData objects. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. structure (pyparsing.ParseResults): structure of tokens derived from lines of text that match an input line history """ for index, item in enumerate(structure.get('input_line_history_items', [])): event_data = VimInfoEventData() event_data.history_value = item[1] event_data.history_type = 'Input Line History' event_data.item_number = index event_data.recorded_time = dfdatetime_posix_time.PosixTime( timestamp=item[5]) parser_mediator.ProduceEventData(event_data) def _ParseDebugLineHistory(self, parser_mediator, structure): """Parses debug line history items and creates VimInfoEventData objects. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. structure (pyparsing.ParseResults): structure of tokens derived from lines of text that match a debug line history """ for index, item in enumerate(structure.get('debug_line_history_items', [])): event_data = VimInfoEventData() event_data.history_value = item[1] event_data.history_type = 'Debug Line History' event_data.item_number = index event_data.recorded_time = dfdatetime_posix_time.PosixTime( timestamp=item[5]) parser_mediator.ProduceEventData(event_data) def _ParseRegistersHistory(self, parser_mediator, structure): """Parses register history items and creates VimInfoEventData objects. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. structure (pyparsing.ParseResults): structure of tokens derived from lines of text that match a Register history """ for item in structure.get('registers_items', []): event_data = VimInfoEventData() event_data.history_value = '\n'.join(item[4]) event_data.history_type = 'Register' event_data.item_number = item[1] event_data.recorded_time = dfdatetime_posix_time.PosixTime( timestamp=item[12]) parser_mediator.ProduceEventData(event_data) def _ParseFilemarksHistory(self, parser_mediator, structure): """Parses filemarks history items and creates VimInfoEventData objects. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. structure (pyparsing.ParseResults): structure of tokens derived from lines of text that match a Filemarks history """ for index, item in enumerate(structure.get('filemarks_items', [])): event_data = VimInfoEventData() event_data.filename = item[4].strip() event_data.history_type = 'File mark' event_data.item_number = index event_data.recorded_time = dfdatetime_posix_time.PosixTime( timestamp=item[5][5]) parser_mediator.ProduceEventData(event_data) def _ParseJumplistHistory(self, parser_mediator, structure): """Parses jumplist items and creates VimInfoEventData objects. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. structure (pyparsing.ParseResults): structure of tokens derived from lines of text that match a JumpList history """ for index, item in enumerate(structure.get('jumplist_items', [])): event_data = VimInfoEventData() event_data.filename = item[3].strip() event_data.history_type = 'Jumplist' event_data.item_number = index event_data.recorded_time = dfdatetime_posix_time.PosixTime( timestamp=item[4][5]) parser_mediator.ProduceEventData(event_data) def _ParseRecord(self, parser_mediator, key, structure): """Parses a pyparsing structure. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. key (str): name of the parsed structure. structure (pyparsing.ParseResults): tokens from a parsed log line. Raises: ParseError: if the structure cannot be parsed. """ if key == 'command_line_history': self._ParseCommandLineHistory(parser_mediator, structure) elif key == 'search_string_history': self._ParseSearchStringHistory(parser_mediator, structure) elif key == 'expression_history': self._ParseExpressionHistory(parser_mediator, structure) elif key == 'input_line_history': self._ParseInputLineHistory(parser_mediator, structure) elif key == 'debug_line_history': self._ParseDebugLineHistory(parser_mediator, structure) elif key == 'registers_history': self._ParseRegistersHistory(parser_mediator, structure) elif key == 'filemarks_history': self._ParseFilemarksHistory(parser_mediator, structure) elif key == 'jumplist_history': self._ParseJumplistHistory(parser_mediator, structure) # TODO(sydp): add support for history marks history lines # elif key == 'history_marks_history': # self._ParseHistoryMarksHistory(self, parser_mediator, structure)
[docs] def CheckRequiredFormat(self, parser_mediator, text_reader): """Check if the log record has the minimal structure required by the parser. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. text_reader (EncodedTextReader): text reader. Returns: bool: True if this is the correct parser, False otherwise. """ try: self._VerifyString(text_reader.lines) except errors.ParseError: return False return True
text_parser.TextLogParser.RegisterPlugin(VimInfoTextPlugin)