diff options
| author | Maximilian Hils <git@maximilianhils.com> | 2019-11-18 22:03:51 +0100 | 
|---|---|---|
| committer | Maximilian Hils <git@maximilianhils.com> | 2019-11-18 22:03:51 +0100 | 
| commit | 74f5fa6a7736f116416c242b159e6b0525e6fe5b (patch) | |
| tree | 0c90e441aea082e91ee9b864f3c98363e1232927 | |
| parent | 7bf06f8ae04697305731ec89a43ebea6da4376b8 (diff) | |
| download | mitmproxy-74f5fa6a7736f116416c242b159e6b0525e6fe5b.tar.gz mitmproxy-74f5fa6a7736f116416c242b159e6b0525e6fe5b.tar.bz2 mitmproxy-74f5fa6a7736f116416c242b159e6b0525e6fe5b.zip | |
wip
| -rw-r--r-- | mitmproxy/addons/core.py | 17 | ||||
| -rw-r--r-- | mitmproxy/addons/view.py | 26 | ||||
| -rw-r--r-- | mitmproxy/command.py | 27 | ||||
| -rw-r--r-- | mitmproxy/tools/console/commander/commander.py | 8 | ||||
| -rw-r--r-- | mitmproxy/tools/console/commands.py | 2 | ||||
| -rw-r--r-- | mitmproxy/tools/console/consoleaddons.py | 11 | ||||
| -rw-r--r-- | test/mitmproxy/tools/console/test_commander.py | 4 | 
7 files changed, 55 insertions, 40 deletions
| diff --git a/mitmproxy/addons/core.py b/mitmproxy/addons/core.py index 1fbeb1e0..55e2e129 100644 --- a/mitmproxy/addons/core.py +++ b/mitmproxy/addons/core.py @@ -83,15 +83,15 @@ class Core:                      )      @command.command("set") -    def set(self, *options: str) -> None: +    def set(self, option: str, *value: 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. If multiple specs are passed, they are joined -            into one separated by spaces. +            Set an option. 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. +            Multiple values are concatenated with a single space.          """ -        strspec = " ".join(options) +        value = " ".join(value) +        strspec = f"{option}={value}"          try:              ctx.options.set(strspec)          except exceptions.OptionsError as e: @@ -168,8 +168,7 @@ class Core:              "reason",          ] -    @command.command( -        "flow.set") +    @command.command("flow.set")      @command.argument("attr", type=mitmproxy.types.Choice("flow.set.options"))      def flow_set(          self, diff --git a/mitmproxy/addons/view.py b/mitmproxy/addons/view.py index c57c34c8..1d57d781 100644 --- a/mitmproxy/addons/view.py +++ b/mitmproxy/addons/view.py @@ -298,16 +298,16 @@ class View(collections.abc.Sequence):      # Filter      @command.command("view.filter.set") -    def set_filter_cmd(self, filtstr: str) -> None: +    def set_filter_cmd(self, filter_expr: str) -> None:          """              Sets the current view filter.          """          filt = None -        if filtstr: -            filt = flowfilter.parse(filtstr) +        if filter_expr: +            filt = flowfilter.parse(filter_expr)              if not filt:                  raise exceptions.CommandError( -                    "Invalid interception filter: %s" % filtstr +                    "Invalid interception filter: %s" % filter_expr                  )          self.set_filter(filt) @@ -412,26 +412,26 @@ class View(collections.abc.Sequence):              ctx.log.alert("Removed %s flows" % len(flows))      @command.command("view.flows.resolve") -    def resolve(self, flowspec: str) -> typing.Sequence[mitmproxy.flow.Flow]: +    def resolve(self, flow_spec: str) -> typing.Sequence[mitmproxy.flow.Flow]:          """              Resolve a flow list specification to an actual list of flows.          """ -        if flowspec == "@all": +        if flow_spec == "@all":              return [i for i in self._store.values()] -        if flowspec == "@focus": +        if flow_spec == "@focus":              return [self.focus.flow] if self.focus.flow else [] -        elif flowspec == "@shown": +        elif flow_spec == "@shown":              return [i for i in self] -        elif flowspec == "@hidden": +        elif flow_spec == "@hidden":              return [i for i in self._store.values() if i not in self._view] -        elif flowspec == "@marked": +        elif flow_spec == "@marked":              return [i for i in self._store.values() if i.marked] -        elif flowspec == "@unmarked": +        elif flow_spec == "@unmarked":              return [i for i in self._store.values() if not i.marked]          else: -            filt = flowfilter.parse(flowspec) +            filt = flowfilter.parse(flow_spec)              if not filt: -                raise exceptions.CommandError("Invalid flow filter: %s" % flowspec) +                raise exceptions.CommandError("Invalid flow filter: %s" % flow_spec)              return [i for i in self._store.values() if filt(i)]      @command.command("view.flows.create") diff --git a/mitmproxy/command.py b/mitmproxy/command.py index 00238f46..7203fe42 100644 --- a/mitmproxy/command.py +++ b/mitmproxy/command.py @@ -3,6 +3,7 @@  """  import functools  import inspect +import re  import sys  import textwrap  import types @@ -284,13 +285,27 @@ class CommandManager:  def unquote(x: str) -> str: -    if x.startswith("'") and x.endswith("'"): -        return x[1:-1] -    if x.startswith('"') and x.endswith('"'): -        return x[1:-1] +    quoted = ( +            (x.startswith('"') and x.endswith('"')) +            or +            (x.startswith("'") and x.endswith("'")) +    ) +    if quoted: +        x = x[1:-1] +        # not sure if this is the right place, but pypyarsing doesn't process escape sequences. +        x = re.sub(r"\\(.)", r"\g<1>", x) +        return x      return x +def quote(val: str) -> str: +    if not val: +        return '""' +    if all(ws not in val for ws in " \r\n\t"): +        return val +    return repr(val) + +  def parsearg(manager: CommandManager, spec: str, argtype: type) -> typing.Any:      """          Convert a string to a argument to the appropriate type. @@ -304,14 +319,14 @@ def parsearg(manager: CommandManager, spec: str, argtype: type) -> typing.Any:          raise exceptions.CommandError from e -def command(name: typing.Optional[str]): +def command(name: typing.Optional[str] = None):      def decorator(function):          @functools.wraps(function)          def wrapper(*args, **kwargs):              verify_arg_signature(function, args, kwargs)              return function(*args, **kwargs) -        wrapper.__dict__["command_name"] = name or function.__name__ +        wrapper.__dict__["command_name"] = name or function.__name__.replace("_", ".")          return wrapper      return decorator diff --git a/mitmproxy/tools/console/commander/commander.py b/mitmproxy/tools/console/commander/commander.py index f826b984..d751422b 100644 --- a/mitmproxy/tools/console/commander/commander.py +++ b/mitmproxy/tools/console/commander/commander.py @@ -14,7 +14,7 @@ import mitmproxy.types  class Completer:      @abc.abstractmethod -    def cycle(self, forward: bool) -> str: +    def cycle(self, forward: bool = True) -> str:          raise NotImplementedError() @@ -32,7 +32,7 @@ class ListCompleter(Completer):          self.options.sort()          self.offset = 0 -    def cycle(self, forward: bool) -> str: +    def cycle(self, forward: bool = True) -> str:          if not self.options:              return self.start          ret = self.options[self.offset] @@ -98,7 +98,7 @@ class CommandBuffer:      def right(self) -> None:          self.cursor = self.cursor + 1 -    def cycle_completion(self, forward: bool) -> None: +    def cycle_completion(self, forward: bool = True) -> None:          if not self.completion:              parts, remaining = self.master.commands.parse_partial(self.text[:self.cursor])              if parts and parts[-1].type != mitmproxy.types.Space: @@ -211,7 +211,7 @@ class CommandEdit(urwid.WidgetWrap):          elif key == "shift tab":              self.cbuf.cycle_completion(False)          elif key == "tab": -            self.cbuf.cycle_completion(True) +            self.cbuf.cycle_completion()          elif len(key) == 1:              self.cbuf.insert(key)          self.update() diff --git a/mitmproxy/tools/console/commands.py b/mitmproxy/tools/console/commands.py index d35a6b8a..26a99b14 100644 --- a/mitmproxy/tools/console/commands.py +++ b/mitmproxy/tools/console/commands.py @@ -25,7 +25,7 @@ class CommandItem(urwid.WidgetWrap):          if self.cmd.parameters:              parts += [                  ("text", " "), -                ("text", " ".join(name for name, t in self.cmd.parameters)), +                ("text", " ".join(str(param) for param in self.cmd.parameters)),              ]          if self.cmd.return_type:              parts += [ diff --git a/mitmproxy/tools/console/consoleaddons.py b/mitmproxy/tools/console/consoleaddons.py index b5263f6f..4288696a 100644 --- a/mitmproxy/tools/console/consoleaddons.py +++ b/mitmproxy/tools/console/consoleaddons.py @@ -287,21 +287,22 @@ class ConsoleAddon:          )      @command.command("console.command") -    def console_command(self, *cmdstr: str) -> None: +    def console_command(self, *cmd_str: str) -> None:          """          Prompt the user to edit a command with a (possibly empty) starting value.          """ -        signals.status_prompt_command.send(partial=" ".join(cmdstr))  # type: ignore +        cmd_str = (command.quote(x) if x else "" for x in cmd_str) +        signals.status_prompt_command.send(partial=" ".join(cmd_str))  # type: ignore      @command.command("console.command.set")      def console_command_set(self, option_name: str) -> None:          """ -        Prompt the user to set an option of the form "key[=value]". +        Prompt the user to set an option.          """          option_value = getattr(self.master.options, option_name, None) -        current_value = option_value if option_value else "" +        option_value = command.quote(option_value)          self.master.commands.execute( -            "console.command set %s=%s" % (option_name, current_value) +            f"console.command set {option_name} {option_value}"          )      @command.command("console.view.keybindings") diff --git a/test/mitmproxy/tools/console/test_commander.py b/test/mitmproxy/tools/console/test_commander.py index ce789d30..6b42de76 100644 --- a/test/mitmproxy/tools/console/test_commander.py +++ b/test/mitmproxy/tools/console/test_commander.py @@ -25,7 +25,7 @@ class TestListCompleter:          for start, options, cycle in tests:              c = commander.ListCompleter(start, options)              for expected in cycle: -                assert c.cycle(True) == expected +                assert c.cycle() == expected  class TestCommandEdit: @@ -252,7 +252,7 @@ class TestCommandBuffer:              cb = commander.CommandBuffer(tctx.master)              cb.text = "foo bar"              cb.cursor = len(cb.text) -            cb.cycle_completion(True) +            cb.cycle_completion()              ch = commander.CommandHistory(tctx.master, 30)              ce = commander.CommandEdit(tctx.master, "se", ch) | 
