From f35e68cd65a31f595237d99774976f56d299b411 Mon Sep 17 00:00:00 2001 From: James Vega Date: Sun, 10 Jan 2010 20:17:10 -0500 Subject: [PATCH] Network: Properly parse WHOIS response The 319 message that indicates which channel(s) a user is in prefix the channel name with the modes (@, +, !, etc.) applied to that user. These need to be stripped from the channel name before we feed it to irc.state.channels.get(), otherwise when irc.state.channels.get() returns None we assume the channel can't be private and leak information. (cherry picked from commit 408ab6f88a04f593f55ab38e33e558c5297d5d77) --- plugins/Network/plugin.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/plugins/Network/plugin.py b/plugins/Network/plugin.py index 10dbdc354..2eb405f01 100644 --- a/plugins/Network/plugin.py +++ b/plugins/Network/plugin.py @@ -1,5 +1,6 @@ ### # Copyright (c) 2002-2004, Jeremiah Fincher +# Copyright (c) 2010, James Vega # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -166,7 +167,19 @@ class Network(callbacks.Plugin): normal = [] halfops = [] for channel in channels: + origchan = channel + channel = channel.lstrip('@%+~!') + # UnrealIRCd uses & for user modes and disallows it as a + # channel-prefix, flying in the face of the RFC. Have to + # handle this specially when processing WHOIS response. + testchan = channel.lstrip('&') + if testchan != channel and irc.isChannel(testchan): + channel = testchan + diff = len(channel) - len(origchan) + modes = origchan[:diff] chan = irc.state.channels.get(channel) + # The user is in a channel the bot is in, so the ircd may have + # responded with otherwise private data. if chan: # Skip channels the callee isn't in. This helps prevents # us leaking information when the channel is +s or the @@ -178,14 +191,14 @@ class Network(callbacks.Plugin): if 's' in chan.modes and \ not ircutils.strEqual(replyMsg.args[0], channel): continue - if channel.startswith('@'): - ops.append(channel[1:]) - elif channel.startswith('%'): - halfops.append(channel[1:]) - elif channel.startswith('+'): - voices.append(channel[1:]) - else: + if not modes: normal.append(channel) + elif utils.iter.any(lambda c: c in modes,('@', '&', '~', '!')): + ops.append(channel[1:]) + elif utils.iter.any(lambda c: c in modes, ('%',)): + halfops.append(channel[1:]) + elif utils.iter.any(lambda c: c in modes, ('+',)): + voices.append(channel[1:]) L = [] if ops: L.append(format('is an op on %L', ops))