diff --git a/plugins/relay.py b/plugins/relay.py index eab73be..f2e09c0 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -176,17 +176,19 @@ def normalize_host(irc, host): """Creates a normalized hostname for the given host suitable for introduction to a remote network (as a relay client).""" log.debug('(%s) relay.normalize_host: IRCd=%s, host=%s', irc.name, irc.protoname, host) - if irc.protoname not in ('inspircd', 'ts6', 'clientbot', 'nefarious'): + + allowed_chars = string.ascii_letters + string.digits + '-.:' + if irc.protoname in ('inspircd', 'ts6', 'clientbot', 'nefarious'): # UnrealIRCd and IRCd-Hybrid don't allow slashes in hostnames - host = host.replace('/', '.') - host = host.replace('\x03', '') # Strip colours - host = host.replace('\x02', '') # Strip bold - host = host.replace('\x1f', '') # Strip underline - host = host.replace('\x1d', '') # Strip italic - host = host.replace('\x0f', '') # Strip color reset - host = host.replace('\x16', '') # Strip reverse color - # And no, I'm not supporting colours in hosts. Screw your IRCd-breaking patches if you think - # this is cool. -GL + allowed_chars += '/' + + if irc.protoname in ('inspircd', 'clientbot', 'nefarious', 'unreal'): + # The above IRCds allow _ in hostnames, while TS6-like IRCds do not. + allowed_chars += '_' + + for char in host: + if char not in allowed_chars: + host = host.replace(char, '-') return host[:63] # Limit hosts to 63 chars for best compatibility diff --git a/protocols/hybrid.py b/protocols/hybrid.py index 05c282a..a79bf93 100644 --- a/protocols/hybrid.py +++ b/protocols/hybrid.py @@ -168,6 +168,7 @@ class HybridProtocol(TS6Protocol): """ # <- :0UY UID dan 1 1451041551 +Facdeiklosuw ~ident localhost 127.0.0.1 0UYAAAAAB * :realname nick = args[0] + self.checkCollision(nick) ts, modes, ident, host, ip, uid, account, realname = args[2:10] if account == '*': account = None diff --git a/protocols/inspircd.py b/protocols/inspircd.py index e1568b0..8dbf7de 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -561,6 +561,7 @@ class InspIRCdProtocol(TS6BaseProtocol): """Handles incoming UID commands (user introduction).""" # :70M UID 70MAAAAAB 1429934638 GL 0::1 hidden-7j810p.9mdf.lrek.0000.0000.IP gl 0::1 1429934638 +Wioswx +ACGKNOQXacfgklnoqvx :realname uid, ts, nick, realhost, host, ident, ip = args[0:7] + self.checkCollision(nick) realname = args[-1] self.irc.users[uid] = userobj = IrcUser(nick, ts, uid, numeric, ident, host, realname, realhost, ip) diff --git a/protocols/ircs2s_common.py b/protocols/ircs2s_common.py index c0e92ba..c8542fb 100644 --- a/protocols/ircs2s_common.py +++ b/protocols/ircs2s_common.py @@ -7,6 +7,18 @@ from pylinkirc.log import log class IRCS2SProtocol(Protocol): + def checkCollision(self, nick): + """ + Nick collision checker. + """ + uid = self.irc.nickToUid(nick) + # If there is a nick collision, we simply alert plugins. Relay will purposely try to + # lose fights and tag nicks instead, while other plugins can choose how to handle this. + if uid: + log.info('(%s) Nick collision on %s/%s, forwarding this to plugins', self.irc.name, + uid, nick) + self.irc.callHooks([self.irc.sid, 'SAVE', {'target': uid}]) + def handle_kill(self, source, command, args): """Handles incoming KILLs.""" killed = args[0] diff --git a/protocols/nefarious.py b/protocols/nefarious.py index 0daba13..8f1ae62 100644 --- a/protocols/nefarious.py +++ b/protocols/nefarious.py @@ -827,6 +827,7 @@ class P10Protocol(IRCS2SProtocol): # <- AB N GL 1 1460673049 ~gl nefarious.midnight.vpn +iw B]AAAB ABAAA :realname nick = args[0] + self.checkCollision(nick) ts, ident, host = args[2:5] realhost = host ip = args[-3] diff --git a/protocols/ts6.py b/protocols/ts6.py index 82c1681..505df58 100644 --- a/protocols/ts6.py +++ b/protocols/ts6.py @@ -499,6 +499,7 @@ class TS6Protocol(TS6BaseProtocol): """Handles incoming EUID commands (user introduction).""" # <- :42X EUID GL 1 1437505322 +ailoswz ~gl 127.0.0.1 127.0.0.1 42XAAAAAB * * :realname nick = args[0] + self.checkCollision(nick) ts, modes, ident, host, ip, uid, realhost, accountname, realname = args[2:11] if realhost == '*': realhost = None diff --git a/protocols/unreal.py b/protocols/unreal.py index 7abaf0a..d3a4934 100644 --- a/protocols/unreal.py +++ b/protocols/unreal.py @@ -336,6 +336,7 @@ class UnrealProtocol(TS6BaseProtocol): # arguments: nick, hopcount?, ts, ident, real-host, UID, services account (0 if none), modes, # displayed host, cloaked (+x) host, base64-encoded IP, and realname nick = args[0] + self.checkCollision(nick) ts, ident, realhost, uid, accountname, modestring, host = args[2:9] if host == '*':