mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-01 01:09:22 +01:00
relay/utils: make mode reversals work with mode changes that affect op statuses.
This commit is contained in:
parent
c82a0a771c
commit
9a139212dd
@ -116,14 +116,23 @@ def save(irc, source, args):
|
||||
irc.msg(source, 'Error: You are not authenticated!')
|
||||
return
|
||||
|
||||
def getPrefixModes(irc, remoteirc, channel, user):
|
||||
def getPrefixModes(irc, remoteirc, channel, user, mlist=None):
|
||||
"""
|
||||
Fetches all prefix modes for a user in a channel that are supported by the
|
||||
remote IRC network given.
|
||||
|
||||
Optionally, an mlist argument can be given to look at an earlier state of
|
||||
the channel, e.g. for checking the op status of a mode setter before their
|
||||
modes are processed and added to the channel state.
|
||||
"""
|
||||
modes = ''
|
||||
mlist = mlist or irc.channels[channel].prefixmodes
|
||||
for pmode in ('owner', 'admin', 'op', 'halfop', 'voice'):
|
||||
if pmode in remoteirc.cmodes: # Mode supported by IRCd
|
||||
mlist = irc.channels[channel].prefixmodes[pmode+'s']
|
||||
userlist = mlist[pmode+'s']
|
||||
log.debug('(%s) getPrefixModes: checking if %r is in %s list: %r',
|
||||
irc.name, user, pmode, mlist)
|
||||
if user in mlist:
|
||||
irc.name, user, pmode, userlist)
|
||||
if user in userlist:
|
||||
modes += remoteirc.cmodes[pmode]
|
||||
return modes
|
||||
|
||||
@ -416,7 +425,7 @@ def handle_privmsg(irc, numeric, command, args):
|
||||
utils.add_hook(handle_privmsg, 'PRIVMSG')
|
||||
utils.add_hook(handle_privmsg, 'NOTICE')
|
||||
|
||||
def checkClaim(irc, channel, sender):
|
||||
def checkClaim(irc, channel, sender, chanobj=None):
|
||||
"""
|
||||
Checks whether the sender of a kick/mode change passes CLAIM checks for
|
||||
a given channel. This returns True if any of the following criteria are met:
|
||||
@ -428,7 +437,13 @@ def checkClaim(irc, channel, sender):
|
||||
5) The originating network is the one that created the relay.
|
||||
"""
|
||||
relay = findRelay((irc.name, channel))
|
||||
sender_modes = getPrefixModes(irc, irc, channel, sender)
|
||||
try:
|
||||
mlist = chanobj.prefixmodes
|
||||
except AttributeError:
|
||||
mlist = None
|
||||
sender_modes = getPrefixModes(irc, irc, channel, sender, mlist=mlist)
|
||||
log.debug('(%s) relay.checkClaim: sender modes (%s/%s) are %s (mlist=%s)', irc.name,
|
||||
sender, channel, sender_modes, mlist)
|
||||
return (not relay) or irc.name == relay[0] or irc.name in db[relay]['claim'] or \
|
||||
any([mode in sender_modes for mode in ('y', 'q', 'a', 'o', 'h')]) \
|
||||
or utils.isInternalClient(irc, sender) or \
|
||||
@ -665,10 +680,11 @@ def handle_mode(irc, numeric, command, args):
|
||||
if irc.name == name or not remoteirc.connected.is_set():
|
||||
continue
|
||||
if utils.isChannel(target):
|
||||
if checkClaim(irc, target, numeric):
|
||||
oldchan = args['oldchan']
|
||||
if checkClaim(irc, target, numeric, chanobj=oldchan):
|
||||
relayModes(irc, remoteirc, numeric, target, modes)
|
||||
else: # Mode change blocked by CLAIM.
|
||||
reversed_modes = utils.reverseModes(irc, target, modes)
|
||||
reversed_modes = utils.reverseModes(irc, target, modes, oldobj=oldchan)
|
||||
log.debug('(%s) Reversing mode changes of %r with %r (CLAIM).',
|
||||
irc.name, modes, reversed_modes)
|
||||
irc.proto.modeClient(irc.pseudoclient.uid, target, reversed_modes)
|
||||
|
27
utils.py
27
utils.py
@ -338,14 +338,19 @@ def _flip(mode):
|
||||
mode.insert(0, '-')
|
||||
return ''.join(mode)
|
||||
|
||||
def reverseModes(irc, target, modes):
|
||||
def reverseModes(irc, target, modes, oldobj=None):
|
||||
"""Reverses/Inverts the mode string or mode list given.
|
||||
|
||||
"+nt-lk" => "-nt+lk"
|
||||
"nt-k" => "-nt+k"
|
||||
[('+m', None), ('+t', None), ('+l', '3'), ('-o', 'person')] =>
|
||||
[('-m', None), ('-t', None), ('-l', '3'), ('+o', 'person')]
|
||||
[('s', None), ('+n', None)] => [('-s', None), ('-n', None)]
|
||||
Optionally, an oldobj argument can be given to look at an earlier state of
|
||||
a channel/user object, e.g. for checking the op status of a mode setter
|
||||
before their modes are processed and added to the channel state.
|
||||
|
||||
This function allows both mode strings or mode lists. Example uses:
|
||||
"+mi-lk test => "-mi+lk test"
|
||||
"mi-k test => "-mi+k test"
|
||||
[('+m', None), ('+r', None), ('+l', '3'), ('-o', 'person')
|
||||
=> {('-m', None), ('-r', None), ('-l', None), ('+o', 'person')})
|
||||
{('s', None), ('+o', 'whoever') => {('-s', None), ('-o', 'whoever')})
|
||||
"""
|
||||
origtype = type(modes)
|
||||
# If the query is a string, we have to parse it first.
|
||||
@ -353,11 +358,12 @@ def reverseModes(irc, target, modes):
|
||||
modes = parseModes(irc, target, modes.split(" "))
|
||||
# Get the current mode list first.
|
||||
if isChannel(target):
|
||||
oldmodes = irc.channels[target].modes.copy()
|
||||
c = oldobj or irc.channels[target]
|
||||
oldmodes = c.modes.copy()
|
||||
possible_modes = irc.cmodes.copy()
|
||||
# For channels, this also includes the list of prefix modes.
|
||||
possible_modes['*A'] += ''.join(irc.prefixmodes)
|
||||
for name, userlist in irc.channels[target].prefixmodes.items():
|
||||
for name, userlist in c.prefixmodes.items():
|
||||
try:
|
||||
oldmodes.update([(irc.cmodes[name[:-1]], u) for u in userlist])
|
||||
except KeyError:
|
||||
@ -366,6 +372,8 @@ def reverseModes(irc, target, modes):
|
||||
oldmodes = irc.users[target].modes
|
||||
possible_modes = irc.umodes
|
||||
newmodes = []
|
||||
log.debug('(%s) reverseModes: old/current mode list for %s is: %s', irc.name,
|
||||
target, oldmodes)
|
||||
for char, arg in modes:
|
||||
# Mode types:
|
||||
# A = Mode that adds or removes a nick or address to a list. Always has a parameter.
|
||||
@ -390,9 +398,12 @@ def reverseModes(irc, target, modes):
|
||||
mpair = (_flip(char), arg)
|
||||
if char[0] != '-' and (mchar, arg) in oldmodes:
|
||||
# Mode is already set.
|
||||
log.debug("(%s) reverseModes: skipping reversing '%s %s' with %s since we're "
|
||||
"setting a mode that's already set.", irc.name, char, arg, mpair)
|
||||
continue
|
||||
newmodes.append(mpair)
|
||||
|
||||
log.debug('(%s) reverseModes: new modes: %s', irc.name, newmodes)
|
||||
if origtype == str:
|
||||
# If the original query is a string, send it back as a string.
|
||||
return joinModes(newmodes)
|
||||
|
Loading…
Reference in New Issue
Block a user