mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-26 12:49:24 +01:00
irclib: Fix support of power prefix chars in RPL_NAMREPLY
nickFromHostmask now (legitimately) complains when it's getting @ or ! at the beginning of a hostmask; so we need to strip them before passing it to nickFromHostmask. Then re-add them before calling c.addUser, because it uses them to sort users in the right sets (ops/halfops/voices). Additionally, this commit replaces the hardcoded set of prefix chars (`@%+&~!`) with the one advertised in ISUPPORT when possible.
This commit is contained in:
parent
aa6bd7257d
commit
d308329461
@ -389,15 +389,15 @@ class ChannelState(utils.python.Object):
|
||||
"""Returns whether the given nick is an halfop, or an op."""
|
||||
return nick in self.halfops or nick in self.ops
|
||||
|
||||
def addUser(self, user):
|
||||
def addUser(self, user, prefix_chars='@%+&~!'):
|
||||
"Adds a given user to the ChannelState. Power prefixes are handled."
|
||||
nick = user.lstrip('@%+&~!')
|
||||
nick = user.lstrip(prefix_chars)
|
||||
if not nick:
|
||||
return
|
||||
# & is used to denote protected users in UnrealIRCd
|
||||
# ~ is used to denote channel owner in UnrealIRCd
|
||||
# ! is used to denote protected users in UltimateIRCd
|
||||
while user and user[0] in '@%+&~!':
|
||||
while user and user[0] in prefix_chars:
|
||||
(marker, user) = (user[0], user[1:])
|
||||
assert user, 'Looks like my caller is passing chars, not nicks.'
|
||||
if marker in '@&~!':
|
||||
@ -963,13 +963,27 @@ class IrcState(IrcCommandDispatcher, log.Firewalled):
|
||||
if channel not in self.channels:
|
||||
self.channels[channel] = ChannelState()
|
||||
c = self.channels[channel]
|
||||
|
||||
# Set of prefixes servers may append before a NAMES reply when
|
||||
# the user is op/halfop/voice/...
|
||||
# https://datatracker.ietf.org/doc/html/draft-hardy-irc-isupport-00#section-4.15
|
||||
prefix = self.supported.get('PREFIX')
|
||||
if prefix is None:
|
||||
prefix_chars = '@%+&~!' # see the comments in addUser
|
||||
else:
|
||||
prefix_chars = prefix.split(')', 1)[-1]
|
||||
|
||||
for item in items.split():
|
||||
if ircutils.isUserHostmask(item):
|
||||
name = ircutils.nickFromHostmask(item)
|
||||
self.nicksToHostmasks[name] = name
|
||||
stripped_item = item.lstrip(prefix_chars)
|
||||
item_prefix = item[0:-len(stripped_item)]
|
||||
if ircutils.isUserHostmask(stripped_item):
|
||||
nick = ircutils.nickFromHostmask(stripped_item)
|
||||
self.nicksToHostmasks[nick] = nick
|
||||
name = item_prefix + nick
|
||||
else:
|
||||
name = item
|
||||
c.addUser(name)
|
||||
c.addUser(name, prefix_chars=prefix_chars)
|
||||
|
||||
if type == '@':
|
||||
c.modes['s'] = None
|
||||
|
||||
|
@ -529,6 +529,41 @@ class IrcStateTestCase(SupyTestCase):
|
||||
st = irclib.IrcState()
|
||||
self.assert_(st.addMsg(self.irc, ircmsgs.IrcMsg('MODE foo +i')) or 1)
|
||||
|
||||
def testNamreply(self):
|
||||
"""RPL_NAMREPLY / reply to NAMES"""
|
||||
|
||||
# Just nicks (à la RFC 1459 + some common prefix chars)
|
||||
st = irclib.IrcState()
|
||||
st.addMsg(self.irc, ircmsgs.IrcMsg(command='353',
|
||||
args=('*', '=', '#chan', 'nick1 @nick2 ~@nick3')))
|
||||
chan_st = st.channels['#chan']
|
||||
self.assertEqual(chan_st.users, ircutils.IrcSet(['nick1', 'nick2', 'nick3']))
|
||||
self.assertEqual(chan_st.ops, ircutils.IrcSet(['nick2', 'nick3']))
|
||||
self.assertEqual(st.nicksToHostmasks, ircutils.IrcDict({}))
|
||||
|
||||
# with userhost-in-names
|
||||
st = irclib.IrcState()
|
||||
st.addMsg(self.irc, ircmsgs.IrcMsg(command='353',
|
||||
args=('*', '=', '#chan', 'nick1!u1@h1 @nick2!u2@h2 ~@nick3!u3@h3')))
|
||||
chan_st = st.channels['#chan']
|
||||
self.assertEqual(chan_st.users, ircutils.IrcSet(['nick1', 'nick2', 'nick3']))
|
||||
self.assertEqual(chan_st.ops, ircutils.IrcSet(['nick2', 'nick3']))
|
||||
self.assertEqual(st.nicksToHostmasks['nick1'], 'nick1')
|
||||
self.assertEqual(st.nicksToHostmasks['nick2'], 'nick2')
|
||||
self.assertEqual(st.nicksToHostmasks['nick3'], 'nick3')
|
||||
|
||||
# Prefixed with chars not in ISUPPORT PREFIX
|
||||
st = irclib.IrcState()
|
||||
st.supported['PREFIX'] = '(ov)@+'
|
||||
st.addMsg(self.irc, ircmsgs.IrcMsg(command='353',
|
||||
args=('*', '=', '#chan', 'nick1!u1@h1 @nick2!u2@h2 ~@nick3!u3@h3')))
|
||||
chan_st = st.channels['#chan']
|
||||
self.assertEqual(chan_st.users, ircutils.IrcSet(['nick1', 'nick2', '~@nick3']))
|
||||
self.assertEqual(chan_st.ops, ircutils.IrcSet(['nick2']))
|
||||
self.assertEqual(st.nicksToHostmasks['nick1'], 'nick1')
|
||||
self.assertEqual(st.nicksToHostmasks['nick2'], 'nick2')
|
||||
self.assertEqual(st.nicksToHostmasks['~@nick3'], '~@nick3')
|
||||
|
||||
|
||||
class IrcCapsTestCase(SupyTestCase, CapNegMixin):
|
||||
def testReqLineLength(self):
|
||||
|
Loading…
Reference in New Issue
Block a user