Beispiel #1
0
    def plugin_pinfo(self, runner, detail_level=0):
        """Generate info dict for a plugin from a plugin runner."""
        plugin_class = getattr(
            runner.session.plugins, runner.plugin_name)._target

        display_fields = [
            ("file", oinspect.find_file(plugin_class)),
            ("Plugin", "%s (%s)" % (plugin_class.__name__, plugin_class.name))]
        if getattr(plugin_class, "table_header", None):
            display_fields.append(
                ("", "This is a Typed Plugin."))

        display_fields += [
            ("Positional Args",
             self.format_parameters(plugin_class, True)),
            ("Keyword Args",
             self.format_parameters(plugin_class, False)),
            ("Docstring", oinspect.getdoc(plugin_class) or ""),
            ("Link", (
                "http://www.rekall-forensic.com/epydocs/%s.%s-class.html" % (
                    plugin_class.__module__, plugin_class.__name__))),
        ]

        # Include the source if required.
        if detail_level > 0:
            info = self.info(plugin_class, detail_level=detail_level)
            display_fields.append(("source", self.format(info["source"])))

        return self._format_fields(display_fields)
    def plugin_pinfo(self, runner, detail_level=0):
        """Generate info dict for a plugin from a plugin runner."""
        plugin_class = getattr(runner.session.plugins,
                               runner.plugin_name)._target

        display_fields = [
            ("file", oinspect.find_file(plugin_class)),
            ("Plugin", "%s (%s)" % (plugin_class.__name__, plugin_class.name))
        ]
        if getattr(plugin_class, "table_header", None):
            display_fields.append(("", "This is a Typed Plugin."))

        display_fields += [
            ("Positional Args", self.format_parameters(plugin_class, True)),
            ("Keyword Args", self.format_parameters(plugin_class, False)),
            ("Docstring", oinspect.getdoc(plugin_class) or ""),
            ("Link",
             ("http://www.rekall-forensic.com/epydocs/%s.%s-class.html" %
              (plugin_class.__module__, plugin_class.__name__))),
        ]

        # Include the source if required.
        if detail_level > 0:
            info = self.info(plugin_class, detail_level=detail_level)
            display_fields.append(("source", self.format(info["source"])))

        return self._format_fields(display_fields)
    def plugin_info(self, runner, **kwargs):
        """Generate info dict for a plugin from a plugin runner."""
        plugin_class = getattr(
            runner.session.plugins, runner.plugin_name)._target

        result = oinspect.Inspector.info(self, plugin_class, **kwargs)
        result["file"] = oinspect.find_file(plugin_class)
        result["type_name"] = "Rekall Plugin (%s)" % plugin_class.__name__
        result["parameters"] = self.format_parameters(plugin_class)
        result["docstring"] = oinspect.getdoc(plugin_class)
        result["link"] = (
            "http://www.rekall-forensic.com/epydocs/%s.%s-class.html" % (
                plugin_class.__module__, plugin_class.__name__))

        # Hide these two fields.
        result["init_definition"] = None
        result["string_form"] = None

        return result
Beispiel #4
0
    def _find_edit_target(shell, args, opts, last_call):
        """Utility method used by magic_edit to find what to edit."""
        def make_filename(arg):
            "Make a filename from the given args"
            try:
                filename = get_py_filename(arg)
            except IOError:
                # If it ends with .py but doesn't already exist, assume we want
                # a new file.
                if arg.endswith('.py'):
                    filename = arg
                else:
                    filename = None
            return filename

        # Set a few locals from the options for convenience:
        opts_prev = 'p' in opts
        opts_raw = 'r' in opts

        # custom exceptions
        class DataIsObject(Exception):
            pass

        # Default line number value
        lineno = opts.get('n', None)

        if opts_prev:
            args = '_%s' % last_call[0]
            if args not in shell.user_ns:
                args = last_call[1]

        # by default this is done with temp files, except when the given
        # arg is a filename
        use_temp = True

        data = ''

        # First, see if the arguments should be a filename.
        filename = make_filename(args)
        if filename:
            use_temp = False
        elif args:
            # Mode where user specifies ranges of lines, like in %macro.
            data = shell.extract_input_lines(args, opts_raw)
            if not data:
                try:
                    # Load the parameter given as a variable. If not a string,
                    # process it as an object instead (below)

                    #print '*** args',args,'type',type(args)  # dbg
                    data = eval(args, shell.user_ns)
                    if not isinstance(data, str):
                        raise DataIsObject

                except (NameError, SyntaxError):
                    # given argument is not a variable, try as a filename
                    filename = make_filename(args)
                    if filename is None:
                        warn(
                            "Argument given (%s) can't be found as a variable "
                            "or as a filename." % args)
                        return (None, None, None)
                    use_temp = False

                except DataIsObject as e:
                    # macros have a special edit function
                    if isinstance(data, Macro):
                        raise MacroToEdit(data) from e

                    # For objects, try to edit the file where they are defined
                    filename = find_file(data)
                    if filename:
                        if 'fakemodule' in filename.lower() and \
                            inspect.isclass(data):
                            # class created by %edit? Try to find source
                            # by looking for method definitions instead, the
                            # __module__ in those classes is FakeModule.
                            attrs = [
                                getattr(data, aname) for aname in dir(data)
                            ]
                            for attr in attrs:
                                if not inspect.ismethod(attr):
                                    continue
                                filename = find_file(attr)
                                if filename and \
                                  'fakemodule' not in filename.lower():
                                    # change the attribute to be the edit
                                    # target instead
                                    data = attr
                                    break

                        m = ipython_input_pat.match(os.path.basename(filename))
                        if m:
                            raise InteractivelyDefined(int(
                                m.groups()[0])) from e

                        datafile = 1
                    if filename is None:
                        filename = make_filename(args)
                        datafile = 1
                        if filename is not None:
                            # only warn about this if we get a real name
                            warn('Could not find file where `%s` is defined.\n'
                                 'Opening a file named `%s`' %
                                 (args, filename))
                    # Now, make sure we can actually read the source (if it was
                    # in a temp file it's gone by now).
                    if datafile:
                        if lineno is None:
                            lineno = find_source_lines(data)
                        if lineno is None:
                            filename = make_filename(args)
                            if filename is None:
                                warn('The file where `%s` was defined '
                                     'cannot be read or found.' % data)
                                return (None, None, None)
                    use_temp = False

        if use_temp:
            filename = shell.mktempfile(data)
            print('IPython will make a temporary file named:', filename)

        # use last_call to remember the state of the previous call, but don't
        # let it be clobbered by successive '-p' calls.
        try:
            last_call[0] = shell.displayhook.prompt_count
            if not opts_prev:
                last_call[1] = args
        except:
            pass

        return filename, lineno, use_temp
Beispiel #5
0
    def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
        """Compute a dict with detailed information about an object.

    This overrides the superclass method for two main purposes:
     * avoid calling str() or repr() on the object
     * use our custom repr

    Args:
      obj: object to inspect.
      oname: (optional) string reference to this object
      formatter: (optional) custom docstring formatter
      info: (optional) previously computed information about obj
      detail_level: (optional) 0 or 1; 1 means "include more detail"

    Returns:
      A dict with information about obj.
    """

        # We want to include the following list of keys for all objects:
        # * name
        # * found
        # * isclass
        # * string_form
        # * type_name
        #
        # For callables, we want to add a subset of:
        # * argspec
        # * call_docstring
        # * definition
        # * docstring
        # * file
        # * init_definition
        # * init_docstring
        # * source_end_line
        # * source_start_line
        # * source_definition
        #
        # For detail_level 1, we include:
        # * file
        # This can be expensive, as the stdlib mechanisms for looking up the file
        # containing obj may call repr(obj).
        #
        # NOTE: These keys should stay in sync with the corresponding list in our
        # frontend code.
        #
        # We want non-None values for:
        # * isalias
        # * ismagic
        # * namespace
        #
        # TODO(b/138128444): Handle class_docstring and call_def, or determine that
        # we're safe ignoring them.

        obj_type = type(obj)
        out = {
            'name': oname,
            'found': True,
            'is_class': inspect.isclass(obj),
            'string_form': None,
            # Fill in empty values.
            'docstring': None,
            'file': None,
            'isalias': False,
            'ismagic': info.ismagic if info else False,
            'namespace': info.namespace if info else '',
        }
        if detail_level >= self.str_detail_level:
            out['string_form'] = _safe_repr(obj)

        if getattr(info, 'ismagic', False):
            out['type_name'] = 'Magic function'
        else:
            out['type_name'] = obj_type.__name__

        # If the object is callable, we want to compute a docstring and related
        # information. We could exit early, but all the code below is in conditional
        # blocks, so there's no need.
        #
        # We can't simply call into the superclass method, as we need to avoid
        # (transitively) calling inspect.getfile(): this function will end up
        # calling repr() on our object.

        # We want to include a docstring if we don't have source, which happens
        # when:
        # * detail_level == 0, or
        # * detail_level == 1 but we can't find source
        # So we first try dealing with detail_level == 1, and then set
        # the docstring if no source is set.
        if detail_level == 1:
            # This should only ever happen if the user has asked for source (eg via
            # `obj??`), so we're OK with potentially calling repr for now.
            # TODO(b/138128444): Ensure we don't call str() or repr().
            source = _getsource(obj)
            if source is None and hasattr(obj, '__class__'):
                source = _getsource(obj.__class__)
            if source is not None:
                out['source'] = source
        if 'source' not in out:
            formatter = formatter or (lambda x: x)
            docstring = formatter(_getdoc(obj) or '<no docstring>')
            if docstring:
                out['docstring'] = docstring

        if _iscallable(obj):
            filename = oinspect.find_file(obj)
            if filename and (filename.endswith(
                ('.py', '.py3', '.pyc')) or '<ipython-input' in filename):
                out['file'] = filename

            line = oinspect.find_source_lines(obj)
            out['source_start_line'] = line
            # inspect.getsourcelines exposes the length of the source as well, which
            # can be used to highlight the entire code block, but find_source_lines
            # currently does not expose this. For now just highlight the first line.
            out['source_end_line'] = line

        # The remaining attributes only apply to classes or callables.
        if inspect.isclass(obj):
            # For classes with an __init__, we set init_definition and init_docstring.
            init = getattr(obj, '__init__', None)
            if init:
                init_docstring = _getdoc(init)
                if init_docstring and init_docstring != _BASE_INIT_DOC:
                    out['init_docstring'] = init_docstring
                init_def = self._getdef(init, oname)
                if init_def:
                    out['init_definition'] = init_def
                src_def = _get_source_definition(init)
                if src_def:
                    out['source_definition'] = src_def
            # For classes, the __init__ method is the method invoked on call, but
            # old-style classes may not have an __init__ method.
            if init:
                argspec = _getargspec_dict(init)
                if argspec:
                    out['argspec'] = argspec
        elif callable(obj):
            definition = self._getdef(obj, oname)
            if definition:
                out['definition'] = definition
            src_def = _get_source_definition(obj)
            if src_def:
                out['source_definition'] = src_def

            if not oinspect.is_simple_callable(obj):
                call_docstring = _getdoc(obj.__call__)
                if call_docstring and call_docstring != _BASE_CALL_DOC:
                    out['call_docstring'] = call_docstring

            out['argspec'] = _getargspec_dict(obj)

        return oinspect.object_info(**out)
Beispiel #6
0
    def _find_edit_target(shell, args, opts, last_call):
        """Utility method used by magic_edit to find what to edit."""

        def make_filename(arg):
            "Make a filename from the given args"
            arg = unquote_filename(arg)
            try:
                filename = get_py_filename(arg)
            except IOError:
                # If it ends with .py but doesn't already exist, assume we want
                # a new file.
                if arg.endswith(".py"):
                    filename = arg
                else:
                    filename = None
            return filename

        # Set a few locals from the options for convenience:
        opts_prev = "p" in opts
        opts_raw = "r" in opts

        # custom exceptions
        class DataIsObject(Exception):
            pass

        # Default line number value
        lineno = opts.get("n", None)

        if opts_prev:
            args = "_%s" % last_call[0]
            if args not in shell.user_ns:
                args = last_call[1]

        # by default this is done with temp files, except when the given
        # arg is a filename
        use_temp = True

        data = ""

        # First, see if the arguments should be a filename.
        filename = make_filename(args)
        if filename:
            use_temp = False
        elif args:
            # Mode where user specifies ranges of lines, like in %macro.
            data = shell.extract_input_lines(args, opts_raw)
            if not data:
                try:
                    # Load the parameter given as a variable. If not a string,
                    # process it as an object instead (below)

                    # print '*** args',args,'type',type(args)  # dbg
                    data = eval(args, shell.user_ns)
                    if not isinstance(data, string_types):
                        raise DataIsObject

                except (NameError, SyntaxError):
                    # given argument is not a variable, try as a filename
                    filename = make_filename(args)
                    if filename is None:
                        warn("Argument given (%s) can't be found as a variable " "or as a filename." % args)
                        return (None, None, None)
                    use_temp = False

                except DataIsObject:
                    # macros have a special edit function
                    if isinstance(data, Macro):
                        raise MacroToEdit(data)

                    # For objects, try to edit the file where they are defined
                    filename = find_file(data)
                    if filename:
                        if "fakemodule" in filename.lower() and inspect.isclass(data):
                            # class created by %edit? Try to find source
                            # by looking for method definitions instead, the
                            # __module__ in those classes is FakeModule.
                            attrs = [getattr(data, aname) for aname in dir(data)]
                            for attr in attrs:
                                if not inspect.ismethod(attr):
                                    continue
                                filename = find_file(attr)
                                if filename and "fakemodule" not in filename.lower():
                                    # change the attribute to be the edit
                                    # target instead
                                    data = attr
                                    break

                        m = ipython_input_pat.match(os.path.basename(filename))
                        if m:
                            raise InteractivelyDefined(int(m.groups()[0]))

                        datafile = 1
                    if filename is None:
                        filename = make_filename(args)
                        datafile = 1
                        if filename is not None:
                            # only warn about this if we get a real name
                            warn(
                                "Could not find file where `%s` is defined.\n"
                                "Opening a file named `%s`" % (args, filename)
                            )
                    # Now, make sure we can actually read the source (if it was
                    # in a temp file it's gone by now).
                    if datafile:
                        if lineno is None:
                            lineno = find_source_lines(data)
                        if lineno is None:
                            filename = make_filename(args)
                            if filename is None:
                                warn("The file where `%s` was defined " "cannot be read or found." % data)
                                return (None, None, None)
                    use_temp = False

        if use_temp:
            filename = shell.mktempfile(data)
            print("IPython will make a temporary file named:", filename)

        # use last_call to remember the state of the previous call, but don't
        # let it be clobbered by successive '-p' calls.
        try:
            last_call[0] = shell.displayhook.prompt_count
            if not opts_prev:
                last_call[1] = args
        except:
            pass

        return filename, lineno, use_temp