From 7e3d7542b9c37e8980c78089a739add9be8b0606 Mon Sep 17 00:00:00 2001 From: jesopo Date: Fri, 7 Sep 2018 15:51:41 +0100 Subject: [PATCH] Support CAP 3.2 --- IRCLineHandler.py | 46 +++++++++++++++++++++++++++++++--------------- IRCServer.py | 3 ++- modules/sasl.py | 11 +++++++++-- 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/IRCLineHandler.py b/IRCLineHandler.py index d9c65126..faa97471 100644 --- a/IRCLineHandler.py +++ b/IRCLineHandler.py @@ -287,27 +287,43 @@ class LineHandler(object): # the server is telling us about its capabilities! def cap(self, event): - capabilities = (event["arbitrary"] or "").split(" ") + capabilities_list = (event["arbitrary"] or "").split(" ") + capabilities = {} + for capability in capabilities_list: + argument = None + if "=" in capability: + capability, argument = capability.split("=", 1) + capabilities[capability] = argument + subcommand = event["args"][1].lower() + is_multiline = len(event["args"]) > 2 and event["args"][2] == "*" if subcommand == "ls": - matched_capabilities = set(capabilities) & CAPABILITIES - if matched_capabilities: - event["server"].queue_capabilities(matched_capabilities) + event["server"].server_capabilities.update(capabilities) + if not is_multiline: + matched_capabilities = set(event["server" + ].server_capabilities.keys()) & CAPABILITIES + if matched_capabilities: + event["server"].queue_capabilities(matched_capabilities) - self.events.on("received.cap").on(subcommand).call( - capabilities=capabilities, server=event["server"]) + self.events.on("received.cap.ls").call( + capabilities=event["server"].server_capabilities, + server=event["server"]) - if subcommand == "ls": - if event["server"].has_capability_queue(): - event["server"].send_capability_queue() - else: - event["server"].send_capability_end() + if event["server"].has_capability_queue(): + event["server"].send_capability_queue() + else: + event["server"].send_capability_end() elif subcommand == "ack": - if not event["server"].waiting_for_capabilities(): - event["server"].send_capability_end() - event["server"].capabilities = set(capabilities) - elif subcommand == "ack" or subcommand == "nack": + event["server"].capabilities.update(capabilities) + if not is_multiline: + self.events.on("received.cap.ack").call( + capabilities=event["server"].capabilities, + server=event["server"]) + + if not event["server"].waiting_for_capabilities(): + event["server"].send_capability_end() + elif subcommand == "nack": event["server"].send_capability_end() # the server is asking for authentication diff --git a/IRCServer.py b/IRCServer.py index 81c64eed..30e29580 100644 --- a/IRCServer.py +++ b/IRCServer.py @@ -30,6 +30,7 @@ class Server(object): self._capability_queue = set([]) self._capabilities_waiting = set([]) self.capabilities = set([]) + self.server_capabilities = {} self.write_buffer = b"" self.buffered_lines = [] @@ -278,7 +279,7 @@ class Server(object): self.send("NICK %s" % nickname) def send_capibility_ls(self): - self.send("CAP LS") + self.send("CAP LS 302") def queue_capability(self, capability): self._capability_queue.add(capability) def queue_capabilities(self, capabilities): diff --git a/modules/sasl.py b/modules/sasl.py index 7bde0813..8df4b3c9 100644 --- a/modules/sasl.py +++ b/modules/sasl.py @@ -14,9 +14,16 @@ class Module(object): event["server"].send_capability_request("sasl") def on_cap(self, event): - if "sasl" in event["capabilities"] and event["server"].get_setting( - "sasl", None): + has_sasl = "sasl" in event["capabilities"] + has_mechanisms = has_sasl and not event["capabilities"]["sasl" + ] == None + has_plaintext = has_mechanisms and "PLAIN" in event["capabilities" + ]["sasl"].split(",") + + if has_sasl and (has_plaintext or not has_mechanisms) and event[ + "server"].get_setting("sasl", None): event["server"].queue_capability("sasl") + def on_cap_ack(self, event): if "sasl" in event["capabilities"]: event["server"].send_authenticate("PLAIN")