Esempio n. 1
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 seleniumwire.thirdparty.mitmproxy.types.CommandTypes.get(
                    parameter.annotation, None):
                raise exceptions.CommandError(
                    f"Argument {name} has an unknown type ({_empty_as_none(t)}) in {func}."
                )
        if self.return_type and not seleniumwire.thirdparty.mitmproxy.types.CommandTypes.get(
                self.return_type, None):
            raise exceptions.CommandError(
                f"Return type has an unknown type ({self.return_type}) in {func}."
            )
Esempio n. 2
0
def typename(t: type) -> str:
    """
        Translates a type to an explanatory string.
    """
    if t == inspect._empty:  # type: ignore
        raise exceptions.CommandError("missing type annotation")
    to = seleniumwire.thirdparty.mitmproxy.types.CommandTypes.get(t, None)
    if not to:
        raise exceptions.CommandError("unsupported type: %s" %
                                      getattr(t, "__name__", t))
    return to.display
Esempio n. 3
0
def parsearg(manager: CommandManager, spec: str, argtype: type) -> typing.Any:
    """
        Convert a string to a argument to the appropriate type.
    """
    t = seleniumwire.thirdparty.mitmproxy.types.CommandTypes.get(argtype, None)
    if not t:
        raise exceptions.CommandError(f"Unsupported argument type: {argtype}")
    try:
        return t.parse(manager, argtype, spec)
    except exceptions.TypeError as e:
        raise exceptions.CommandError(str(e)) from e
Esempio n. 4
0
    def flow_set(self, flows: typing.Sequence[flow.Flow], attr: str,
                 value: str) -> None:
        """
            Quickly set a number of common values on flows.
        """
        val: typing.Union[int, str] = value
        if attr == "status_code":
            try:
                val = int(val)  # type: ignore
            except ValueError as v:
                raise exceptions.CommandError(
                    "Status code is not an integer: %s" % val) from v

        updated = []
        for f in flows:
            req = getattr(f, "request", None)
            rupdate = True
            if req:
                if attr == "method":
                    req.method = val
                elif attr == "host":
                    req.host = val
                elif attr == "path":
                    req.path = val
                elif attr == "url":
                    try:
                        req.url = val
                    except ValueError as e:
                        raise exceptions.CommandError("URL %s is invalid: %s" %
                                                      (repr(val), e)) from e
                else:
                    self.rupdate = False

            resp = getattr(f, "response", None)
            supdate = True
            if resp:
                if attr == "status_code":
                    resp.status_code = val
                    if val in status_codes.RESPONSES:
                        resp.reason = status_codes.RESPONSES[
                            val]  # type: ignore
                elif attr == "reason":
                    resp.reason = val
                else:
                    supdate = False

            if rupdate or supdate:
                updated.append(f)

        ctx.master.addons.trigger("update", updated)
        ctx.log.alert("Set %s on  %s flows." % (attr, len(updated)))
Esempio n. 5
0
 def call(self, command_name: str,
          *args: typing.Sequence[typing.Any]) -> typing.Any:
     """
     Call a command with native arguments. May raise CommandError.
     """
     if command_name not in self.commands:
         raise exceptions.CommandError("Unknown command: %s" % command_name)
     return self.commands[command_name].func(*args)
Esempio n. 6
0
def verify_arg_signature(f: typing.Callable, args: typing.Iterable[typing.Any],
                         kwargs: dict) -> None:
    sig = inspect.signature(f)
    try:
        sig.bind(*args, **kwargs)
    except TypeError as v:
        raise exceptions.CommandError("command argument mismatch: %s" %
                                      v.args[0])
Esempio n. 7
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)
Esempio n. 8
0
 def options_save(
         self, path: seleniumwire.thirdparty.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
Esempio n. 9
0
 def options_load(
         self, path: seleniumwire.thirdparty.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
Esempio n. 10
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),
     )
Esempio n. 11
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 != seleniumwire.thirdparty.mitmproxy.types.Space
     ]
     return self.call_strings(command_name, args)
Esempio n. 12
0
 def set(self, option: str, value: str = "") -> None:
     """
         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 = f"{option}={value}"
     try:
         ctx.options.set(strspec)
     except exceptions.OptionsError as e:
         raise exceptions.CommandError(e) from e
Esempio n. 13
0
 def call(self, args: typing.Sequence[str]) -> typing.Any:
     """
     Call the command with a list of arguments. At this point, all
     arguments are strings.
     """
     bound_args = self.prepare_args(args)
     ret = self.func(*bound_args.args, **bound_args.kwargs)
     if ret is None and self.return_type is None:
         return
     typ = seleniumwire.thirdparty.mitmproxy.types.CommandTypes.get(
         self.return_type)
     assert typ
     if not typ.is_valid(self.manager, typ, ret):
         raise exceptions.CommandError(
             f"{self.name} returned unexpected data - expected {typ.display}"
         )
     return ret
Esempio n. 14
0
    def prepare_args(self,
                     args: typing.Sequence[str]) -> inspect.BoundArguments:
        try:
            bound_arguments = self.signature.bind(*args)
        except TypeError:
            expected = f'Expected: {str(self.signature.parameters)}'
            received = f'Received: {str(args)}'
            raise exceptions.CommandError(
                f"Command argument mismatch: \n    {expected}\n    {received}")

        for name, value in bound_arguments.arguments.items():
            convert_to = self.signature.parameters[name].annotation
            bound_arguments.arguments[name] = parsearg(self.manager, value,
                                                       convert_to)

        bound_arguments.apply_defaults()

        return bound_arguments