3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-12-24 11:42:51 +01:00

Irc, clientbot: disallow unsetting bans that don't exist

This fixes an infinite loop when:
- Clientbot modesync is enabled
- 2 or more clientbot linked networks show unsetting modes that weren't enabled (e.g. charybdis)
- A user removes a ban

The workaround in clientbot prevents this process from triggering an infinite loop when a mode change acknowledgement is received for unsetting a non-existant ban,
though multiple -b mode changes may still be seen due to race conditions in updating the various networks' states.
This commit is contained in:
James Lu 2016-10-07 20:38:45 -07:00
parent 386c71475a
commit 72ca41df33
2 changed files with 16 additions and 3 deletions

View File

@ -601,7 +601,13 @@ class Irc():
# Must have parameter.
log.debug('Mode %s: This mode must have parameter.', mode)
arg = args.pop(0)
if prefix == '-' and mode in supported_modes['*B'] and arg == '*':
if prefix == '-':
log.debug('(%s) parseModes: checking if +%s %s is in old modes list: %s', self.name, mode, arg, oldmodes)
if (mode, arg) not in oldmodes:
# Ignore attempts to unset bans that don't exist.
log.debug("(%s) parseModes(): ignoring removal of non-existent list mode +%s %s", self.name, mode, arg)
continue
elif prefix == '-' and mode in supported_modes['*B'] and arg == '*':
# Charybdis allows unsetting +k without actually
# knowing the key by faking the argument when unsetting
# as a single "*".

View File

@ -184,7 +184,13 @@ class ClientbotWrapperProtocol(Protocol):
"""Sends channel MODE changes."""
if utils.isChannel(channel):
extmodes = []
for modepair in modes:
# Re-parse all channel modes locally to eliminate anything invalid, such as unbanning
# things that were never banned. This prevents the bot from getting caught in a loop
# with IRCd MODE acknowledgements.
# FIXME: More related safety checks should be added for this.
log.debug('(%s) mode: re-parsing modes %s', self.irc.name, modes)
joined_modes = self.irc.joinModes(modes)
for modepair in self.irc.parseModes(channel, joined_modes):
log.debug('(%s) mode: checking if %s a prefix mode: %s', self.irc.name, modepair, self.irc.prefixmodes)
if modepair[0][-1] in self.irc.prefixmodes:
if self.irc.isInternalClient(modepair[1]):
@ -599,7 +605,8 @@ class ClientbotWrapperProtocol(Protocol):
if self.irc.isInternalClient(target):
log.debug('(%s) Suppressing MODE change hook for internal client %s', self.irc.name, target)
return
return {'target': target, 'modes': changedmodes, 'channeldata': oldobj}
if changedmodes:
return {'target': target, 'modes': changedmodes, 'channeldata': oldobj}
def handle_nick(self, source, command, args):
"""Handles NICK changes."""