From 037cc98cac2c2891c46862f261255ab81e62dfc6 Mon Sep 17 00:00:00 2001 From: nyuszika7h Date: Tue, 5 Aug 2014 11:22:56 +0200 Subject: [PATCH] Fix capability negotiation --- src/irclib.py | 48 +++++++++++++++++++++------------------------ test/test_irclib.py | 8 +++++++- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/irclib.py b/src/irclib.py index bae4d5186..00a7c6d49 100644 --- a/src/irclib.py +++ b/src/irclib.py @@ -654,7 +654,6 @@ class Irc(IrcCommandDispatcher): self._setNonResettingVariables() self._queueConnectMessages() self.startedSync = ircutils.IrcDict() - self.caps = set(['account-notify', 'extended-join']) def isChannel(self, s): """Helper function to check whether a given string is a channel on @@ -939,7 +938,16 @@ class Irc(IrcCommandDispatcher): return - self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('LS',))) + sasl = self.sasl_username and self.sasl_password + + if sasl: + self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('REQ', 'sasl'))) + + self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('REQ', 'account-notify'))) + self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('REQ', 'extended-join'))) + + if not sasl: + self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('END',))) if self.password: log.info('%s: Queuing PASS command, not logging the password.', @@ -958,7 +966,7 @@ class Irc(IrcCommandDispatcher): self.queueMsg(ircmsgs.user(self.ident, self.user)) def doAuthenticate(self, msg): - if msg.args[0] == '+': + if len(msg.args) == 1 and msg.args[0] == '+': log.info('%s: Authenticating using SASL.', self.network) authstring = base64.b64encode('\0'.join([ @@ -970,30 +978,18 @@ class Irc(IrcCommandDispatcher): self.queueMsg(ircmsgs.IrcMsg(command='AUTHENTICATE', args=(authstring,))) def doCap(self, msg): - if self.sasl_password: - if self.sasl_username: - self.caps.append('sasl') - else: - log.warning('%s: SASL username is not set, unable to ' - 'identify.', self.network) + if len(msg.args) == 3: + for cap in msg.args[2].split(' '): + if msg.args[1] == 'ACK': + log.info('%s: Server acknowledged capability %r', + self.network, cap) - for cap in msg.args[2].split(' '): - if msg.args[1] == 'LS' and cap in self.caps: - log.debug('%s: Requesting capability %r', self.network, cap) - self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('REQ', cap))) - elif msg.args[1] == 'ACK': - log.info('%s: Server acknowledged capability %r', - self.network, cap) - - if cap == 'sasl': - self.queueMsg(ircmsgs.IrcMsg(command='AUTHENTICATE', - args=('PLAIN',))) - elif msg.args[1] == 'NAK': - log.warning('%s: Server refused capability %r', - self.network, cap) - - if cap == 'sasl': - self.queueMsg(ircmsgs.IrcMsg(command='CAP', args=('END',))) + if cap == 'sasl': + self.queueMsg(ircmsgs.IrcMsg(command='AUTHENTICATE', + args=('PLAIN',))) + elif msg.args[1] == 'NAK': + log.warning('%s: Server refused capability %r', + self.network, cap) def do903(self, msg): log.info('%s: SASL authentication successful', self.network) diff --git a/test/test_irclib.py b/test/test_irclib.py index 4eade6100..607850567 100644 --- a/test/test_irclib.py +++ b/test/test_irclib.py @@ -385,6 +385,10 @@ class IrcTestCase(SupyTestCase): m = self.irc.takeMsg() self.failUnless(m.command == 'CAP', 'Expected CAP, got %r.' % m) m = self.irc.takeMsg() + self.failUnless(m.command == 'CAP', 'Expected CAP, got %r.' % m) + m = self.irc.takeMsg() + self.failUnless(m.command == 'CAP', 'Expected CAP, got %r.' % m) + m = self.irc.takeMsg() self.failUnless(m.command == 'USER', 'Expected USER, got %r.' % m) def testPingResponse(self): @@ -482,7 +486,9 @@ class IrcCallbackTestCase(SupyTestCase): user = 'user any user' conf.supybot.user.setValue(user) expected = [ircmsgs.nick(nick), - ircmsgs.IrcMsg(command='CAP', args=('LS',)), + ircmsgs.IrcMsg(command='CAP', args=('REQ', 'account-notify')), + ircmsgs.IrcMsg(command='CAP', args=('REQ', 'extended-join')), + ircmsgs.IrcMsg(command='CAP', args=('END',)), ircmsgs.user('limnoria', user)] irc = irclib.Irc('test') msgs = [irc.takeMsg()]