Example #1
0
    def register(self, addon):
        """
            Register an addon, call its load event, and then register all its
            sub-addons. This should be used by addons that dynamically manage
            addons.

            If the calling addon is already running, it should follow with
            running and configure events. Must be called within a current
            context.
        """
        for a in traverse([addon]):
            name = _get_name(a)
            if name in self.lookup:
                raise exceptions.AddonManagerError(
                    "An addon called '%s' already exists." % name
                )
        l = Loader(self.master)
        self.invoke_addon(addon, "load", l)
        for a in traverse([addon]):
            name = _get_name(a)
            self.lookup[name] = a
        for a in traverse([addon]):
            self.master.commands.collect_commands(a)
        self.master.options.process_deferred()
        return addon
Example #2
0
 def invoke_addon_sync(self, addon, event: hooks.Hook):
     """
         Invoke an event on an addon and all its children.
     """
     for addon, func in self._iter_hooks(addon, event):
         if inspect.iscoroutinefunction(func):
             raise exceptions.AddonManagerError(
                 f"Async handler {event.name} ({addon}) cannot be called from sync context"
             )
         func(*event.args())
Example #3
0
 def invoke_addon(self, addon, name, *args, **kwargs):
     """
         Invoke an event on an addon and all its children.
     """
     if name not in eventsequence.Events:
         raise exceptions.AddonManagerError("Unknown event: %s" % name)
     for a in traverse([addon]):
         func = getattr(a, name, None)
         if func:
             if callable(func):
                 func(*args, **kwargs)
             elif isinstance(func, types.ModuleType):
                 # we gracefully exclude module imports with the same name as hooks.
                 # For example, a user may have "from mitmproxy import log" in an addon,
                 # which has the same name as the "log" hook. In this particular case,
                 # we end up in an error loop because we "log" this error.
                 pass
             else:
                 raise exceptions.AddonManagerError(
                     "Addon handler {} ({}) not callable".format(name, a))
Example #4
0
 def invoke_addon(self, addon, name, *args, **kwargs):
     """
         Invoke an event on an addon and all its children. This method must
         run within an established handler context.
     """
     if name not in eventsequence.Events:
         name = "event_" + name
     for a in traverse([addon]):
         func = getattr(a, name, None)
         if func:
             if not callable(func):
                 raise exceptions.AddonManagerError(
                     "Addon handler %s not callable" % name)
             func(*args, **kwargs)
Example #5
0
    def remove(self, addon):
        """
            Remove an addon and all its sub-addons.

            If the addon is not in the chain - that is, if it's managed by a
            parent addon - it's the parent's responsibility to remove it from
            its own addons attribute.
        """
        for a in traverse([addon]):
            n = _get_name(a)
            if n not in self.lookup:
                raise exceptions.AddonManagerError("No such addon: %s" % n)
            self.chain = [i for i in self.chain if i is not a]
            del self.lookup[_get_name(a)]
        self.invoke_addon(addon, "done")
Example #6
0
 def invoke_addon(self, addon, event: hooks.Hook):
     """
         Invoke an event on an addon and all its children.
     """
     assert isinstance(event, hooks.Hook)
     for a in traverse([addon]):
         func = getattr(a, event.name, None)
         if func:
             if callable(func):
                 func(*event.args())
             elif isinstance(func, types.ModuleType):
                 # we gracefully exclude module imports with the same name as hooks.
                 # For example, a user may have "from mitmproxy import log" in an addon,
                 # which has the same name as the "log" hook. In this particular case,
                 # we end up in an error loop because we "log" this error.
                 pass
             else:
                 raise exceptions.AddonManagerError(
                     f"Addon handler {event.name} ({a}) not callable")
Example #7
0
 def _iter_hooks(self, addon, event: hooks.Hook):
     """
         Enumerate all hook callables belonging to the given addon
     """
     assert isinstance(event, hooks.Hook)
     for a in traverse([addon]):
         func = getattr(a, event.name, None)
         if func:
             if callable(func):
                 yield a, func
             elif isinstance(func, types.ModuleType):
                 # we gracefully exclude module imports with the same name as hooks.
                 # For example, a user may have "from mitmproxy import log" in an addon,
                 # which has the same name as the "log" hook. In this particular case,
                 # we end up in an error loop because we "log" this error.
                 pass
             else:
                 raise exceptions.AddonManagerError(
                     f"Addon handler {event.name} ({a}) not callable")
Example #8
0
    def register(self, addon):
        """
            Register an addon, call its load event, and then register all its
            sub-addons. This should be used by addons that dynamically manage
            addons.

            If the calling addon is already running, it should follow with
            running and configure events. Must be called within a current
            context.
        """
        api_changes = {
            # mitmproxy 6 -> mitmproxy 7
            "clientconnect": "client_connected",
            "clientdisconnect": "client_disconnected",
            "serverconnect": "server_connect and server_connected",
            "serverdisconnect": "server_disconnected",
        }
        for a in traverse([addon]):
            for old, new in api_changes.items():
                if hasattr(a, old):
                    ctx.log.warn(
                        f"The {old} event has been removed, use {new} instead. "
                        f"For more details, see https://docs.mitmproxy.org/stable/addons-events/."
                    )
            name = _get_name(a)
            if name in self.lookup:
                raise exceptions.AddonManagerError(
                    "An addon called '%s' already exists." % name)
        l = Loader(self.master)
        self.invoke_addon(addon, LoadHook(l))
        for a in traverse([addon]):
            name = _get_name(a)
            self.lookup[name] = a
        for a in traverse([addon]):
            self.master.commands.collect_commands(a)
        self.master.options.process_deferred()
        return addon