Skip to content

Commit

Permalink
Added a report_error method for the renderers. JsonRenderer now encod…
Browse files Browse the repository at this point in the history
…es errors in the json.

R=amoser@google.com

Review URL: https://codereview.appspot.com/91090044
  • Loading branch information
scudette committed May 5, 2014
1 parent 473fe8e commit d78a43e
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 36 deletions.
6 changes: 6 additions & 0 deletions rekall/plugins/overlays/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ def size(self):
# The length is really determined by the terminator here.
return len(self.v())

def __getstate__(self):
result = super(String, self).__getstate__()
result["value"] = str(self)

return result


class Signature(String):
"""A string forming a signature."""
Expand Down
8 changes: 7 additions & 1 deletion rekall/plugins/tools/json_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ def _decode(self, item):
if not isinstance(item, dict):
return self._decode_value(item)

elif isinstance(item, str):
return self._decode_value(item)

state = {}
for k, v in item.items():
decoded_key = self._decode_value(k)
Expand Down Expand Up @@ -162,6 +165,9 @@ def RenderStatement(self, statement, renderer):
elif command == "s":
renderer.section(**self._decode(statement[1]))

elif command == "e":
renderer.report_error(statement[1])

elif command == "f":
args = [self._decode(x) for x in statement[1:]]
renderer.format(*args)
Expand All @@ -180,7 +186,7 @@ def render(self, renderer):
decompressing them.
"""
if self.file:
self.fd = open(file)
self.fd = open(self.file)

if self.fd is None:
raise ValueError("Need a filename or a file descriptor.")
Expand Down
2 changes: 2 additions & 0 deletions rekall/plugins/windows/registry/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,8 @@ class RegistryPlugin(common.WindowsCommandPlugin):

@classmethod
def args(cls, parser):
super(RegistryPlugin, cls).args(parser)

parser.add_argument(
"-o", "--hive-offsets", default=None,
action=config.ArrayIntParser, nargs="+",
Expand Down
55 changes: 24 additions & 31 deletions rekall/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,10 @@ def RunPlugin(self, plugin_cls, *pos_args, **kwargs):

ui_renderer = ui_renderer_cls(session=self, fd=fd, pager=pager)

try:
# Start the renderer before instantiating the plugin to allow
# rendering of reported progress in the constructor.
with ui_renderer.start(plugin_name=plugin_name):
# Start the renderer before instantiating the plugin to allow
# rendering of reported progress in the constructor.
with ui_renderer.start(plugin_name=plugin_name):
try:
kwargs['session'] = self

# If we were passed an instance we do not instantiate it.
Expand All @@ -415,34 +415,27 @@ def RunPlugin(self, plugin_cls, *pos_args, **kwargs):
# Now wait for the user to exit the pager.
pager.flush()

return result
return result

except plugin.InvalidArgs, e:
logging.error("Invalid Args (Try info plugins.%s): %s",
plugin_cls.name, e)

except plugin.Error, e:
self.error(plugin_cls, e)

except KeyboardInterrupt:
if self.debug:
pdb.post_mortem(sys.exc_info()[2])

self.report_progress("Aborted!\r\n", force=True)

except Exception, e:
# If anything goes wrong, we break into a debugger here.
ui_renderer.report_error(traceback.format_exc())
if debug:
pdb.post_mortem(sys.exc_info()[2])

except plugin.InvalidArgs, e:
logging.error("Invalid Args (Try info plugins.%s): %s",
plugin_cls.name, e)

except plugin.Error, e:
self.error(plugin_cls, e)

except KeyboardInterrupt:
if self.debug:
pdb.post_mortem(sys.exc_info()[2])

self.report_progress("Aborted!\r\n", force=True)

except Exception, e:
# If anything goes wrong, we break into a debugger here.
if debug:
# With debug on, we use traceback to print detailed information
# about the error, because pdb can sometimes get it wrong.
_, _, trace = sys.exc_info()
logging.error(
"Detailed error:\n%s",
traceback.format_exc(),
)
pdb.post_mortem(sys.exc_info()[2])
else:
logging.error("Error: %s", e)
raise

def LoadProfile(self, filename, use_cache=True):
Expand Down
11 changes: 7 additions & 4 deletions rekall/ui/json_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ def _encode_value(self, value):

# The hash of the object is not in the lexicon.
if encoded_id is None:
# Create a new ID to encode the base64 encoded string itself.
encoded_b64_id = self._get_encoded_id(b64)

# Create a new ID to store the list encoded string.
encoded_id = self.lexicon_counter = self.lexicon_counter + 1
# Store the list encoded string under this new ID.
Expand Down Expand Up @@ -154,6 +151,9 @@ def _encode(self, item):
elif isinstance(item, (unicode, int, long, float)):
return self._get_encoded_id(item)

elif isinstance(item, str):
return self._encode_value(item)

else:
raise RuntimeError("Unable to encode objects of type %s" %
type(item))
Expand All @@ -165,7 +165,7 @@ def _encode(self, item):
return result

def format(self, formatstring, *args):
statement = [self._encode(formatstring)]
statement = ["f", self._encode(formatstring)]
for arg in args:
# Just store the statement in the output.
statement.append(self._encode(arg))
Expand All @@ -176,6 +176,9 @@ def section(self, name=None, **kwargs):
kwargs["name"] = name
self.SendMessage(["s", self._encode(kwargs)])

def report_error(self, message):
self.SendMessage(["e", message])

def table_header(self, columns=None, **kwargs):
# TODO: Remove this when all calls are done with kwargs.
kwargs["columns"] = columns
Expand Down
7 changes: 7 additions & 0 deletions rekall/ui/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
A renderer is used by plugins to produce formatted output.
"""
import gc
import logging
import time
import re
import os
Expand Down Expand Up @@ -394,6 +395,12 @@ def record(self, record_data):
def color(self, target, **kwargs):
return self.colorizer.Render(target, **kwargs)

def report_error(self, message):
"""Render the error in an appropriate way."""
# By default just log the error. Visual renderers may choose to render
# errors in a distinctive way.
logging.error(message)

def RenderProgress(self, message=" %(spinner)s", *args, **kwargs):
# Only write once per second.
now = time.time()
Expand Down

0 comments on commit d78a43e

Please sign in to comment.