#!/usr/bin/python # -*- coding: utf-8 -*- # # Copyright 2012 The Plaso Project Authors. # Please see the AUTHORS file for details on individual authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Contains functions for outputting as l2t_csv. Author description at: http://code.google.com/p/log2timeline/wiki/l2t_csv """ import logging import re from plaso.formatters import manager as formatters_manager from plaso.lib import errors from plaso.lib import output from plaso.lib import timelib from plaso.lib import utils from plaso.output import helper class L2tcsv(output.FileLogOutputFormatter): """CSV format used by log2timeline, with 17 fixed fields.""" FORMAT_ATTRIBUTE_RE = re.compile('{([^}]+)}') def Start(self): """Returns a header for the output.""" # Build a hostname and username dict objects. self._hostnames = {} if self.store: self._hostnames = helper.BuildHostDict(self.store) self._preprocesses = {} for info in self.store.GetStorageInformation(): if hasattr(info, 'store_range'): for store_number in range( info.store_range[0], info.store_range[1] + 1): self._preprocesses[store_number] = info self.filehandle.WriteLine( u'date,time,timezone,MACB,source,sourcetype,type,user,host,short,desc,' u'version,filename,inode,notes,format,extra\n') def WriteEvent(self, event_object): """Write a single event.""" try: self.EventBody(event_object) except errors.NoFormatterFound: logging.error(u'Unable to output line, no formatter found.') logging.error(event_object) def EventBody(self, event_object): """Formats data as l2t_csv and writes to the filehandle from OutputFormater. Args: event_object: The event object (EventObject). Raises: errors.NoFormatterFound: If no formatter for that event is found. """ if not hasattr(event_object, 'timestamp'): return # TODO: move this to an output module interface. event_formatter = formatters_manager.EventFormatterManager.GetFormatter( event_object) if not event_formatter: raise errors.NoFormatterFound( u'Unable to find event formatter for: {0:s}.'.format( event_object.DATA_TYPE)) msg, msg_short = event_formatter.GetMessages(event_object) source_short, source_long = event_formatter.GetSources(event_object) date_use = timelib.Timestamp.CopyToDatetime( event_object.timestamp, self.zone) extras = [] format_variables = self.FORMAT_ATTRIBUTE_RE.findall( event_formatter.format_string) for key in event_object.GetAttributes(): if key in utils.RESERVED_VARIABLES or key in format_variables: continue # Force a string conversion since some of the extra attributes # can be numbers or bools. value = getattr(event_object, key) extras.append(u'{0:s}: {1!s} '.format(key, value)) extra = ' '.join(extras) inode = getattr(event_object, 'inode', '-') if inode == '-': if hasattr(event_object, 'pathspec') and hasattr( event_object.pathspec, 'image_inode'): inode = event_object.pathspec.image_inode hostname = getattr(event_object, 'hostname', u'') # TODO: move this into a base output class. username = getattr(event_object, 'username', u'-') if self.store: if not hostname: hostname = self._hostnames.get(event_object.store_number, u'-') pre_obj = self._preprocesses.get(event_object.store_number) if pre_obj: check_user = pre_obj.GetUsernameById(username) if check_user != '-': username = check_user row = ( '{0:02d}/{1:02d}/{2:04d}'.format( date_use.month, date_use.day, date_use.year), '{0:02d}:{1:02d}:{2:02d}'.format( date_use.hour, date_use.minute, date_use.second), self.zone, helper.GetLegacy(event_object), source_short, source_long, getattr(event_object, 'timestamp_desc', u'-'), username, hostname, msg_short, msg, '2', getattr(event_object, 'display_name', u'-'), inode, getattr(event_object, 'notes', u'-'), # Notes field placeholder. getattr(event_object, 'parser', u'-'), extra.replace('\n', u'-').replace('\r', u'')) out_write = u'{0:s}\n'.format( u','.join(unicode(x).replace(',', u' ') for x in row)) self.filehandle.WriteLine(out_write)