3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-12-11 20:49:33 +01:00

relay: fix channel not found errors on LINK when remote casemapping differs

This can happen, e.g. if the remote network uses casemapping=ascii and has a channel containing "|", and the local network uses casemapping=rfc1459.

Thanks to iTzNavic for reporting.
This commit is contained in:
James Lu 2021-02-27 12:00:59 -08:00
parent 537c643ed0
commit 4500e27931

View File

@ -2450,8 +2450,12 @@ def link(irc, source, args):
args = link_parser.parse_args(args) args = link_parser.parse_args(args)
# Normalize channel case # Normalize channel case. For the target channel it's possible for the local and remote casemappings
channel = irc.to_lower(str(args.channel)) # to differ - if we find the unnormalized channel name in the list, we should just use that.
# This mainly affects channels with e.g. | in them.
channel_orig = str(args.channel)
channel_norm = irc.to_lower(channel_orig)
localchan = irc.to_lower(str(args.localchannel or args.channel)) localchan = irc.to_lower(str(args.localchannel or args.channel))
remotenet = args.remotenet remotenet = args.remotenet
@ -2495,58 +2499,61 @@ def link(irc, source, args):
irc.error('Channel %r is already part of a relay.' % localchan) irc.error('Channel %r is already part of a relay.' % localchan)
return return
try: if (remotenet, channel_orig) in db:
entry = db[(remotenet, channel)] channel = channel_orig
except KeyError: elif (remotenet, channel_norm) in db:
channel = channel_norm
else:
irc.error('No such relay %r exists.' % args.channel) irc.error('No such relay %r exists.' % args.channel)
return return
else: entry = db[(remotenet, channel)]
whitelist_mode = entry.get('use_whitelist', False)
if ((not whitelist_mode) and irc.name in entry['blocked_nets']) or \ whitelist_mode = entry.get('use_whitelist', False)
(whitelist_mode and irc.name not in entry.get('allowed_nets', set())): if ((not whitelist_mode) and irc.name in entry['blocked_nets']) or \
irc.error('Access denied (target channel is not open to links).') (whitelist_mode and irc.name not in entry.get('allowed_nets', set())):
log.warning('(%s) relay: Blocking link request %s%s -> %s%s from %s due to LINKACL (whitelist_mode=%s)', irc.error('Access denied (target channel is not open to links).')
irc.name, irc.name, localchan, remotenet, channel, log.warning('(%s) relay: Blocking link request %s%s -> %s%s from %s due to LINKACL (whitelist_mode=%s)',
irc.get_hostmask(source), whitelist_mode) irc.name, irc.name, localchan, remotenet, channel,
irc.get_hostmask(source), whitelist_mode)
return
for link in entry['links']:
if link[0] == irc.name:
irc.error("Remote channel '%s%s' is already linked here "
"as %r." % (remotenet, args.channel, link[1]))
return return
for link in entry['links']:
if link[0] == irc.name:
irc.error("Remote channel '%s%s' is already linked here "
"as %r." % (remotenet, args.channel, link[1]))
return
if args.force_ts: if args.force_ts:
permissions.check_permissions(irc, source, ['relay.link.force_ts', 'relay.link.force']) permissions.check_permissions(irc, source, ['relay.link.force_ts', 'relay.link.force'])
log.info("(%s) relay: Forcing link %s%s -> %s%s", irc.name, irc.name, localchan, remotenet, log.info("(%s) relay: Forcing link %s%s -> %s%s", irc.name, irc.name, localchan, remotenet,
args.channel) args.channel)
else: else:
if not world.networkobjects[remotenet].connected.is_set(): if not world.networkobjects[remotenet].connected.is_set():
log.debug('(%s) relay: Blocking link request %s%s -> %s%s because the target ' log.debug('(%s) relay: Blocking link request %s%s -> %s%s because the target '
'network is down', irc.name, irc.name, localchan, remotenet, args.channel) 'network is down', irc.name, irc.name, localchan, remotenet, args.channel)
irc.error("The target network %s is not connected; refusing to link (you may be " irc.error("The target network %s is not connected; refusing to link (you may be "
"able to override this with the --force option)." % remotenet) "able to override this with the --force option)." % remotenet)
return return
our_ts = irc.channels[localchan].ts our_ts = irc.channels[localchan].ts
if channel not in world.networkobjects[remotenet].channels: if channel not in world.networkobjects[remotenet].channels:
irc.error("Unknown target channel %r." % channel) irc.error("Unknown target channel %r." % channel)
return return
their_ts = world.networkobjects[remotenet].channels[channel].ts their_ts = world.networkobjects[remotenet].channels[channel].ts
if (our_ts < their_ts) and irc.has_cap('has-ts'): if (our_ts < their_ts) and irc.has_cap('has-ts'):
log.debug('(%s) relay: Blocking link request %s%s -> %s%s due to bad TS (%s < %s)', irc.name, log.debug('(%s) relay: Blocking link request %s%s -> %s%s due to bad TS (%s < %s)', irc.name,
irc.name, localchan, remotenet, channel, our_ts, their_ts) irc.name, localchan, remotenet, channel, our_ts, their_ts)
irc.error("The channel creation date (TS) on %s (%s) is lower than the target " irc.error("The channel creation date (TS) on %s (%s) is lower than the target "
"channel's (%s); refusing to link. You should clear the local channel %s first " "channel's (%s); refusing to link. You should clear the local channel %s first "
"before linking, or use a different local channel (you may be able to " "before linking, or use a different local channel (you may be able to "
"override this with the --force option)." % (localchan, our_ts, their_ts, localchan)) "override this with the --force option)." % (localchan, our_ts, their_ts, localchan))
return return
entry['links'].add((irc.name, localchan)) entry['links'].add((irc.name, localchan))
log.info('(%s) relay: Channel %s linked to %s%s by %s.', irc.name, log.info('(%s) relay: Channel %s linked to %s%s by %s.', irc.name,
localchan, remotenet, args.channel, irc.get_hostmask(source)) localchan, remotenet, args.channel, irc.get_hostmask(source))
initialize_channel(irc, localchan) initialize_channel(irc, localchan)
irc.reply('Done.') irc.reply('Done.')
link = utils.add_cmd(link, featured=True) link = utils.add_cmd(link, featured=True)
def delink(irc, source, args): def delink(irc, source, args):