diff --git a/src/ircutils.py b/src/ircutils.py index a4d246ff8..227f2804f 100644 --- a/src/ircutils.py +++ b/src/ircutils.py @@ -60,7 +60,11 @@ def debug(s, *args): """Prints a debug string. Most likely replaced by our logging debug.""" print('***', s % args) -userHostmaskRe = re.compile(r'^\S+!\S+@\S+$') +def warning(s, *args): + """Prints a debug string. Most likely replaced by our logging debug.""" + print('###', s % args) + +userHostmaskRe = re.compile(r'^(?P\S+?)!(?P\S+?)@(?P\S+)$') def isUserHostmask(s): """Returns whether or not the string s is a valid User hostmask.""" return userHostmaskRe.match(s) is not None @@ -91,9 +95,17 @@ def hostFromHostmask(hostmask): def splitHostmask(hostmask): """hostmask => (nick, user, host) Returns the nick, user, host of a user hostmask.""" - assert isUserHostmask(hostmask) - nick, rest = hostmask.rsplit('!', 1) - user, host = rest.rsplit('@', 1) + m = userHostmaskRe.match(hostmask) + assert m is not None, hostmask + nick = m.group("nick") + user = m.group("user") + host = m.group("host") + if set("!@") & set(nick+user+host): + # There should never be either of these characters in the part. + # As far as I know it never happens in practice aside from networks + # broken by design. + warning("Invalid hostmask format: %s", hostmask) + # TODO: error if strictRfc is True return (minisix.intern(nick), minisix.intern(user), minisix.intern(host)) def joinHostmask(nick, ident, host): diff --git a/src/log.py b/src/log.py index 7d3a63d4c..24bd5648c 100644 --- a/src/log.py +++ b/src/log.py @@ -329,6 +329,7 @@ atexit.register(logging.shutdown) # ircutils will work without this, but it's useful. ircutils.debug = debug +ircutils.warning = warning def getPluginLogger(name): if not conf.supybot.log.plugins.individualLogfiles(): diff --git a/test/test_ircutils.py b/test/test_ircutils.py index 5629686cc..55269afe5 100644 --- a/test/test_ircutils.py +++ b/test/test_ircutils.py @@ -113,6 +113,17 @@ class FunctionsTestCase(SupyTestCase): self.assertFalse(ircutils.isUserHostmask('@')) self.assertFalse(ircutils.isUserHostmask('!bar@baz')) + def testSplitHostmask(self): + # This is the only valid case: + self.assertEqual(ircutils.splitHostmask('foo!bar@baz'), + ('foo', 'bar', 'baz')) + + # Extravagant cases that never happen on real networks: + self.assertEqual(ircutils.splitHostmask('foo!bar@baz!qux'), + ('foo', 'bar', 'baz!qux')) + self.assertEqual(ircutils.splitHostmask('foo!bar@baz!qux@quux'), + ('foo', 'bar', 'baz!qux@quux')) + def testIsChannel(self): self.assertTrue(ircutils.isChannel('#')) self.assertTrue(ircutils.isChannel('&'))