Example #1
0
 def key_unbind_focus(self) -> None:
     """
         Un-bind the shortcut key currently focused in the key binding viewer.
     """
     b = self._keyfocus()
     try:
         self.master.keymap.remove(b.key, b.contexts)
     except ValueError as v:
         raise exceptions.CommandError(v)
Example #2
0
 def options_reset_current(self) -> None:
     """
         Reset the current option in the options editor.
     """
     fv = self.master.window.current("options")
     if not fv:
         raise exceptions.CommandError("Not viewing options.")
     self.master.commands.call_strings("options.reset.one",
                                       [fv.current_name()])
Example #3
0
    def flowview_mode_set(self, mode: str) -> None:
        """
            Set the display mode for the current flow view.
        """
        fv = self.master.window.current_window("flowview")
        if not fv:
            raise exceptions.CommandError("Not viewing a flow.")
        idx = fv.body.tab_offset

        if mode not in [i.name.lower() for i in contentviews.views]:
            raise exceptions.CommandError("Invalid flowview mode.")

        try:
            self.master.commands.call_strings(
                "view.settings.setval",
                ["@focus", "flowview_mode_%s" % (idx, ), mode])
        except exceptions.CommandError as e:
            ctx.log.error(str(e))
Example #4
0
 def load_file(self, path: mitmproxy.types.Path) -> None:
     """
         Load flows from file, and add them to the replay queue.
     """
     try:
         flows = io.read_flows_from_paths([path])
     except exceptions.FlowReadException as e:
         raise exceptions.CommandError(str(e))
     self.start_replay(flows)
Example #5
0
    def call_strings(self, command_name: str,
                     args: typing.Sequence[str]) -> typing.Any:
        """
        Call a command using a list of string arguments. May raise CommandError.
        """
        if command_name not in self.commands:
            raise exceptions.CommandError("Unknown command: %s" % command_name)

        return self.commands[command_name].call(args)
Example #6
0
 def options_save(self, path: mitmproxy.types.Path) -> None:
     """
         Save options to a file.
     """
     try:
         optmanager.save(ctx.options, path)
     except OSError as e:
         raise exceptions.CommandError("Could not save options - %s" %
                                       e) from e
Example #7
0
    def flowview_mode_set(self, mode: str) -> None:
        """
            Set the display mode for the current flow view.
        """
        fv = self.master.window.current_window("flowview")
        if not fv:
            raise exceptions.CommandError("Not viewing a flow.")
        idx = fv.body.tab_offset

        if mode not in [i.name.lower() for i in contentviews.views]:
            raise exceptions.CommandError("Invalid flowview mode.")

        try:
            cmd = 'view.settings.setval @focus flowview_mode_%s %s' % (idx,
                                                                       mode)
            self.master.commands.execute(cmd)
        except exceptions.CommandError as e:
            signals.status_message.send(message=str(e))
Example #8
0
 def options_load(self, path: mitmproxy.types.Path) -> None:
     """
         Load options from a file.
     """
     try:
         optmanager.load_paths(ctx.options, path)
     except (OSError, exceptions.OptionsError) as e:
         raise exceptions.CommandError("Could not load options - %s" %
                                       e) from e
Example #9
0
    def call(self, args: typing.Sequence[str]):
        """
            Call the command with a set of arguments. At this point, all argumets are strings.
        """
        if len(self.paramtypes) != len(args):
            raise exceptions.CommandError("Usage: %s" % self.signature_help())

        pargs = []
        for i in range(len(args)):
            pargs.append(parsearg(self.manager, args[i], self.paramtypes[i]))

        with self.manager.master.handlecontext():
            ret = self.func(*pargs)

        if not typecheck.check_command_return_type(ret, self.returntype):
            raise exceptions.CommandError("Command returned unexpected data")

        return ret
Example #10
0
def parsearg(manager: CommandManager, spec: str, argtype: type) -> typing.Any:
    """
        Convert a string to a argument to the appropriate type.
    """
    if argtype == str:
        return spec
    elif argtype == typing.Sequence[flow.Flow]:
        return manager.call_args("console.resolve", [spec])
    elif argtype == flow.Flow:
        flows = manager.call_args("console.resolve", [spec])
        if len(flows) != 1:
            raise exceptions.CommandError(
                "Command requires one flow, specification matched %s." %
                len(flows))
        return flows[0]
    else:
        raise exceptions.CommandError("Unsupported argument type: %s" %
                                      argtype)
Example #11
0
 def clip(self, fmt: str, f: flow.Flow) -> None:
     """
         Export a flow to the system clipboard.
     """
     if fmt not in formats:
         raise exceptions.CommandError("No such export format: %s" % fmt)
     func = formats[fmt]  # type: typing.Any
     v = strutils.always_str(func(f))
     pyperclip.copy(v)
Example #12
0
 def load_file(self, path: mitmproxy.types.Path) -> None:
     """
         Append server responses from file.
     """
     try:
         flows = io.read_flows_from_paths([path])
     except exceptions.FlowReadException as e:
         raise exceptions.CommandError(str(e))
     self.add_flows(flows)
Example #13
0
 def edit_focus(self, part: str) -> None:
     """
         Edit a component of the currently focused flow.
     """
     flow = self.master.view.focus.flow
     # This shouldn't be necessary once this command is "console.edit @focus",
     # but for now it is.
     if not flow:
         raise exceptions.CommandError("No flow selected.")
     if part == "cookies":
         self.master.switch_view("edit_focus_cookies")
     elif part == "form":
         self.master.switch_view("edit_focus_form")
     elif part == "path":
         self.master.switch_view("edit_focus_path")
     elif part == "query":
         self.master.switch_view("edit_focus_query")
     elif part == "request-headers":
         self.master.switch_view("edit_focus_request_headers")
     elif part == "response-headers":
         self.master.switch_view("edit_focus_response_headers")
     elif part in ("request-body", "response-body"):
         if part == "request-body":
             message = flow.request
         else:
             message = flow.response
         if not message:
             raise exceptions.CommandError("Flow has no {}.".format(
                 part.split("-")[0]))
         c = self.master.spawn_editor(
             message.get_content(strict=False) or b"")
         # Fix an issue caused by some editors when editing a
         # request/response body. Many editors make it hard to save a
         # file without a terminating newline on the last line. When
         # editing message bodies, this can cause problems. For now, I
         # just strip the newlines off the end of the body when we return
         # from an editor.
         message.content = c.rstrip(b"\n")
     elif part == "set-cookies":
         self.master.switch_view("edit_focus_setcookies")
     elif part in ["url", "method", "status_code", "reason"]:
         self.master.commands.call("console.command flow.set @focus %s " %
                                   part)
Example #14
0
    def __init__(self, manager: "CommandManager", name: str, func: typing.Callable) -> None:
        self.name = name
        self.manager = manager
        self.func = func
        self.signature = inspect.signature(self.func)

        if func.__doc__:
            txt = func.__doc__.strip()
            self.help = "\n".join(textwrap.wrap(txt))
        else:
            self.help = None

        # This fails with a CommandException if types are invalid
        for name, parameter in self.signature.parameters.items():
            t = parameter.annotation
            if not mitmproxy.types.CommandTypes.get(parameter.annotation, None):
                raise exceptions.CommandError(f"Argument {name} has an unknown type {t} in {func}.")
        if self.return_type and not mitmproxy.types.CommandTypes.get(self.return_type, None):
            raise exceptions.CommandError(f"Return type has an unknown type ({self.return_type}) in {func}.")
Example #15
0
def request_content_for_console(request: http.Request) -> str:
    try:
        text = request.get_text(strict=True)
        assert text
    except ValueError:
        # shlex.quote doesn't support a bytes object
        # see https://github.com/python/cpython/pull/10871
        raise exceptions.CommandError("Request content must be valid unicode")
    escape_control_chars = {chr(i): f"\\x{i:02x}" for i in range(32)}
    return "".join(escape_control_chars.get(x, x) for x in text)
Example #16
0
def parsearg(manager: CommandManager, spec: str, argtype: type) -> typing.Any:
    """
        Convert a string to a argument to the appropriate type.
    """
    if isinstance(argtype, Choice):
        cmd = argtype.options_command
        opts = manager.call(cmd)
        if spec not in opts:
            raise exceptions.CommandError(
                "Invalid choice: see %s for options" % cmd)
        return spec
    elif issubclass(argtype, str):
        return spec
    elif argtype == bool:
        if spec == "true":
            return True
        elif spec == "false":
            return False
        else:
            raise exceptions.CommandError(
                "Booleans are 'true' or 'false', got %s" % spec)
    elif issubclass(argtype, int):
        try:
            return int(spec)
        except ValueError as e:
            raise exceptions.CommandError("Expected an integer, got %s." %
                                          spec)
    elif argtype == typing.Sequence[flow.Flow]:
        return manager.call_args("view.resolve", [spec])
    elif argtype == Cuts:
        return manager.call_args("cut", [spec])
    elif argtype == flow.Flow:
        flows = manager.call_args("view.resolve", [spec])
        if len(flows) != 1:
            raise exceptions.CommandError(
                "Command requires one flow, specification matched %s." %
                len(flows))
        return flows[0]
    elif argtype == typing.Sequence[str]:
        return [i.strip() for i in spec.split(",")]
    else:
        raise exceptions.CommandError("Unsupported argument type: %s" %
                                      argtype)
Example #17
0
 def start_replay(self, flows: typing.Sequence[flow.Flow]) -> None:
     """
         Replay requests from flows.
     """
     for f in flows:
         if f.live:
             raise exceptions.CommandError("Can't replay live flow.")
     self.flows = list(flows)
     ctx.log.alert("Replaying %s flows." % len(self.flows))
     ctx.master.addons.trigger("update", [])
Example #18
0
 def key_bind(self, contexts: typing.Sequence[str], key: str,
              cmd: mitmproxy.types.Cmd, *args: mitmproxy.types.Arg) -> None:
     """
         Bind a shortcut key.
     """
     try:
         self.master.keymap.add(key, cmd + " " + " ".join(args), contexts,
                                "")
     except ValueError as v:
         raise exceptions.CommandError(v)
Example #19
0
 def options_reset_one(self, name: str) -> None:
     """
         Reset one option to its default value.
     """
     if name not in ctx.options:
         raise exceptions.CommandError("No such option: %s" % name)
     setattr(
         ctx.options,
         name,
         ctx.options.default(name),
     )
Example #20
0
 def set_filter_cmd(self, f: str) -> None:
     """
         Sets the current view filter.
     """
     filt = None
     if f:
         filt = flowfilter.parse(f)
         if not filt:
             raise exceptions.CommandError(
                 "Invalid interception filter: %s" % f)
     self.set_filter(filt)
Example #21
0
 def set_order(self, order: str) -> None:
     """
         Sets the current view order.
     """
     if order not in self.orders:
         raise exceptions.CommandError("Unknown flow order: %s" % order)
     order_key = self.orders[order]
     self.order_key = order_key
     newview = sortedcontainers.SortedListWithKey(key=order_key)
     newview.update(self._view)
     self._view = newview
Example #22
0
 def set_filter_cmd(self, filter_expr: str) -> None:
     """
         Sets the current view filter.
     """
     filt = None
     if filter_expr:
         try:
             filt = flowfilter.parse(filter_expr)
         except ValueError as e:
             raise exceptions.CommandError(str(e)) from e
     self.set_filter(filt)
Example #23
0
    def edit_focus(self, flow_part: str) -> None:
        """
            Edit a component of the currently focused flow.
        """
        flow = self.master.view.focus.flow
        # This shouldn't be necessary once this command is "console.edit @focus",
        # but for now it is.
        if not flow:
            raise exceptions.CommandError("No flow selected.")
        flow.backup()

        require_dummy_response = (flow_part in ("response-headers",
                                                "response-body", "set-cookies")
                                  and flow.response is None)
        if require_dummy_response:
            flow.response = http.HTTPResponse.make()
        if flow_part == "cookies":
            self.master.switch_view("edit_focus_cookies")
        elif flow_part == "urlencoded form":
            self.master.switch_view("edit_focus_urlencoded_form")
        elif flow_part == "multipart form":
            self.master.switch_view("edit_focus_multipart_form")
        elif flow_part == "path":
            self.master.switch_view("edit_focus_path")
        elif flow_part == "query":
            self.master.switch_view("edit_focus_query")
        elif flow_part == "request-headers":
            self.master.switch_view("edit_focus_request_headers")
        elif flow_part == "response-headers":
            self.master.switch_view("edit_focus_response_headers")
        elif flow_part in ("request-body", "response-body"):
            if flow_part == "request-body":
                message = flow.request
            else:
                message = flow.response
            c = self.master.spawn_editor(
                message.get_content(strict=False) or b"")
            # Fix an issue caused by some editors when editing a
            # request/response body. Many editors make it hard to save a
            # file without a terminating newline on the last line. When
            # editing message bodies, this can cause problems. For now, I
            # just strip the newlines off the end of the body when we return
            # from an editor.
            message.content = c.rstrip(b"\n")
        elif flow_part == "set-cookies":
            self.master.switch_view("edit_focus_setcookies")
        elif flow_part == "url":
            url = flow.request.url.encode()
            edited_url = self.master.spawn_editor(url)
            url = edited_url.rstrip(b"\n")
            flow.request.url = url.decode()
        elif flow_part in ["method", "status_code", "reason"]:
            self.master.commands.call_strings(
                "console.command", ["flow.set", "@focus", flow_part])
Example #24
0
def parsearg(manager: CommandManager, spec: str, argtype: type) -> typing.Any:
    """
        Convert a string to a argument to the appropriate type.
    """
    t = mitmproxy.types.CommandTypes.get(argtype, None)
    if not t:
        raise exceptions.CommandError("Unsupported argument type: %s" % argtype)
    try:
        return t.parse(manager, argtype, spec)  # type: ignore
    except exceptions.TypeError as e:
        raise exceptions.CommandError from e
Example #25
0
 def my_tools_save_flow_to_txt(self,
                               flows: typing.Sequence[mitmproxy.flow.Flow],
                               path: mitmproxy.types.Path):
     try:
         f = self.my_tools_open_file(path)
     except IOError as v:
         raise exceptions.CommandError(v) from v
     stream = io.FlowWriter(f)
     for i in flows:
         stream.add(i)
     f.close()
Example #26
0
 def set(self, spec: str) -> None:
     """
         Set an option of the form "key[=value]". When the value is omitted,
         booleans are set to true, strings and integers are set to None (if
         permitted), and sequences are emptied. Boolean values can be true,
         false or toggle.
     """
     try:
         ctx.options.set(spec)
     except exceptions.OptionsError as e:
         raise exceptions.CommandError(e) from e
Example #27
0
 def create(self, method: str, url: str) -> None:
     try:
         req = http.HTTPRequest.make(method.upper(), url)
     except ValueError as e:
         raise exceptions.CommandError("Invalid URL: %s" % e)
     c = connections.ClientConnection.make_dummy(("", 0))
     s = connections.ServerConnection.make_dummy((req.host, req.port))
     f = http.HTTPFlow(c, s)
     f.request = req
     f.request.headers["Host"] = req.host
     self.add([f])
Example #28
0
def cleanup_request(f: flow.Flow):
    if not hasattr(f, "request"):
        raise exceptions.CommandError("Can't export flow with no request.")
    request = f.request.copy()  # type: ignore
    request.decode(strict=False)
    # a bit of clean-up
    if request.method == 'GET' and request.headers.get("content-length",
                                                       None) == "0":
        request.headers.pop('content-length')
    request.headers.pop(':authority', None)
    return request
Example #29
0
 def clip(self, fmt: str, f: flow.Flow) -> None:
     """
         Export a flow to the system clipboard.
     """
     if fmt not in formats:
         raise exceptions.CommandError("No such export format: %s" % fmt)
     func: typing.Any = formats[fmt]
     v = strutils.always_str(func(f))
     try:
         pyperclip.copy(v)
     except pyperclip.PyperclipException as e:
         ctx.log.error(str(e))
Example #30
0
 def execute(self, cmdstr: str) -> typing.Any:
     """
     Execute a command string. May raise CommandError.
     """
     parts, _ = self.parse_partial(cmdstr)
     if not parts:
         raise exceptions.CommandError(f"Invalid command: {cmdstr!r}")
     command_name, *args = [
         unquote(part.value) for part in parts
         if part.type != mitmproxy.types.Space
     ]
     return self.call_strings(command_name, args)