diff --git a/scripts/supybot b/scripts/supybot index b1db5f33a..d4701edda 100755 --- a/scripts/supybot +++ b/scripts/supybot @@ -322,8 +322,7 @@ if __name__ == '__main__': import callbacks import Owner - import ircutils - ircutils.strictRfc = options.strictRfc + conf.strictRfc = options.strictRfc irc = irclib.Irc(nick, user, ident, password) callback = Owner.Class() diff --git a/src/conf.py b/src/conf.py index 55c0e54e2..c72899987 100644 --- a/src/conf.py +++ b/src/conf.py @@ -53,6 +53,12 @@ _pluginsDir = os.path.join(installDir, 'plugins') ### allowEval = False +### +# strictRfc: Determines whether the bot will very strictly follow the RCE +# or whether it will allow things like @ and . in nicks. +### +strictRfc = False + supybot = registry.Group() supybot.setName('supybot') diff --git a/src/ircmsgs.py b/src/ircmsgs.py index a503d5986..cc472cbeb 100644 --- a/src/ircmsgs.py +++ b/src/ircmsgs.py @@ -43,6 +43,7 @@ import fix import re import string +import conf import ircutils ### @@ -282,103 +283,118 @@ isUserHostmask = ircutils.isUserHostmask def pong(payload, prefix=''): """Takes a payload and returns the proper PONG IrcMsg.""" - assert payload, 'PONG requires a payload' + if conf.strictRfc: + assert payload, 'PONG requires a payload' return IrcMsg(prefix=prefix, command='PONG', args=(payload,)) def ping(payload, prefix=''): """Takes a payload and returns the proper PING IrcMsg.""" - assert payload, 'PING requires a payload' + if conf.strictRfc: + assert payload, 'PING requires a payload' return IrcMsg(prefix=prefix, command='PING', args=(payload,)) def op(channel, nick, prefix=''): """Returns a MODE to op nick on channel.""" - assert isChannel(channel), repr(channel) - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command=MODE, args=(channel, '+o', nick)) def ops(channel, nicks, prefix=''): """Returns a MODE to op each of nicks on channel.""" - assert isChannel(channel), repr(channel) - assert nicks, 'Nicks must not be empty.' - assert all(isNick, nicks), nicks + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert nicks, 'Nicks must not be empty.' + assert all(isNick, nicks), nicks return IrcMsg(prefix=prefix, command=MODE, args=(channel, '+' + ('o'*len(nicks))) + tuple(nicks)) def deop(channel, nick, prefix=''): """Returns a MODE to deop nick on channel.""" - assert isChannel(channel), repr(channel) - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command=MODE, args=(channel, '-o', nick)) def deops(channel, nicks, prefix=''): """Returns a MODE to deop each of nicks on channel.""" - assert isChannel(channel), repr(channel) - assert nicks, 'Nicks must not be empty.' - assert all(isNick, nicks), nicks + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert nicks, 'Nicks must not be empty.' + assert all(isNick, nicks), nicks return IrcMsg(prefix=prefix, command=MODE, args=(channel, '-' + ('o'*len(nicks))) + tuple(nicks)) def halfop(channel, nick, prefix=''): """Returns a MODE to halfop nick on channel.""" - assert isChannel(channel), repr(channel) - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command=MODE, args=(channel, '+h', nick)) def halfops(channel, nicks, prefix=''): """Returns a MODE to halfop each of nicks on channel.""" - assert isChannel(channel), repr(channel) - assert nicks, 'Nicks must not be empty.' - assert all(isNick, nicks), nicks + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert nicks, 'Nicks must not be empty.' + assert all(isNick, nicks), nicks return IrcMsg(prefix=prefix, command=MODE, args=(channel, '+' + ('h'*len(nicks))) + tuple(nicks)) def dehalfop(channel, nick, prefix=''): """Returns a MODE to dehalfop nick on channel.""" - assert isChannel(channel), repr(channel) - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command=MODE, args=(channel, '-h', nick)) def dehalfops(channel, nicks, prefix=''): """Returns a MODE to dehalfop each of nicks on channel.""" - assert isChannel(channel), repr(channel) - assert nicks, 'Nicks must not be empty.' - assert all(isNick, nicks), nicks + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert nicks, 'Nicks must not be empty.' + assert all(isNick, nicks), nicks return IrcMsg(prefix=prefix, command=MODE, args=(channel, '-' + ('h'*len(nicks))) + tuple(nicks)) def voice(channel, nick, prefix=''): """Returns a MODE to voice nick on channel.""" - assert isChannel(channel), repr(channel) - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command=MODE, args=(channel, '+v', nick)) def voices(channel, nicks, prefix=''): """Returns a MODE to voice each of nicks on channel.""" - assert isChannel(channel), repr(channel) - assert nicks, 'Nicks must not be empty.' - assert all(isNick, nicks) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert nicks, 'Nicks must not be empty.' + assert all(isNick, nicks) return IrcMsg(prefix=prefix, command=MODE, args=(channel, '+' + ('v'*len(nicks))) + tuple(nicks)) def devoice(channel, nick, prefix=''): """Returns a MODE to devoice nick on channel.""" - assert isChannel(channel), repr(channel) - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command=MODE, args=(channel, '-v', nick)) def devoices(channel, nicks, prefix=''): """Returns a MODE to devoice each of nicks on channel.""" - assert isChannel(channel), repr(channel) - assert nicks, 'Nicks must not be empty.' - assert all(isNick, nicks), nicks + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert nicks, 'Nicks must not be empty.' + assert all(isNick, nicks), nicks return IrcMsg(prefix=prefix, command=MODE, args=(channel, '-' + ('v'*len(nicks))) + tuple(nicks)) def ban(channel, hostmask, exception='', prefix=''): """Returns a MODE to ban nick on channel.""" - assert isChannel(channel), repr(channel) - assert isUserHostmask(hostmask), repr(hostmask) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isUserHostmask(hostmask), repr(hostmask) modes = [('+b', hostmask)] if exception: modes.append(('+e', exception)) @@ -387,29 +403,33 @@ def ban(channel, hostmask, exception='', prefix=''): def bans(channel, hostmasks, exceptions=(), prefix=''): """Returns a MODE to ban each of nicks on channel.""" - assert isChannel(channel), repr(channel) - assert all(isUserHostmask, hostmasks), hostmasks + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert all(isUserHostmask, hostmasks), hostmasks modes = [('+b', s) for s in hostmasks] + [('+e', s) for s in exceptions] return IrcMsg(prefix=prefix, command=MODE, args=[channel] + ircutils.joinModes(modes)) def unban(channel, hostmask, prefix=''): """Returns a MODE to unban nick on channel.""" - assert isChannel(channel), repr(channel) - assert isUserHostmask(hostmask), repr(hostmask) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isUserHostmask(hostmask), repr(hostmask) return IrcMsg(prefix=prefix, command=MODE, args=(channel, '-b', hostmask)) def unbans(channel, hostmasks, prefix=''): """Returns a MODE to unban each of nicks on channel.""" - assert isChannel(channel), repr(channel) - assert all(isUserHostmask, hostmasks), hostmasks + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert all(isUserHostmask, hostmasks), hostmasks return IrcMsg(prefix=prefix, command=MODE, args=(channel, '-' + ('b'*len(hostmasks)), hostmasks)) def kick(channel, nick, msg='', prefix=''): """Returns a KICK to kick nick from channel with the message msg.""" - assert isChannel(channel), repr(channel) - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert isNick(nick), repr(nick) if msg: return IrcMsg(prefix=prefix, command='KICK', args=(channel, nick, msg)) else: @@ -418,8 +438,9 @@ def kick(channel, nick, msg='', prefix=''): def kicks(channel, nicks, msg='', prefix=''): """Returns a KICK to kick each of nicks from channel with the message msg. """ - assert isChannel(channel), repr(channel) - assert all(isNick, nicks), nicks + if conf.strictRfc: + assert isChannel(channel), repr(channel) + assert all(isNick, nicks), nicks if msg: return IrcMsg(prefix=prefix, command='KICK', args=(channel, ','.join(nicks), msg)) @@ -429,50 +450,33 @@ def kicks(channel, nicks, msg='', prefix=''): def privmsg(recipient, msg, prefix=''): """Returns a PRIVMSG to recipient with the message msg.""" - assert (isChannel(recipient) or isNick(recipient)), repr(recipient) - assert msg, 'msg must not be empty.' + if conf.strictRfc: + assert (isChannel(recipient) or isNick(recipient)), repr(recipient) + assert msg, 'msg must not be empty.' return IrcMsg(prefix=prefix, command='PRIVMSG', args=(recipient, msg)) def action(recipient, msg, prefix=''): """Returns a PRIVMSG ACTION to recipient with the message msg.""" - assert (isChannel(recipient) or isNick(recipient)), repr(recipient) + if conf.strictRfc: + assert (isChannel(recipient) or isNick(recipient)), repr(recipient) return IrcMsg(prefix=prefix, command='PRIVMSG', args=(recipient,'\x01ACTION %s\x01'% msg)) def notice(recipient, msg, prefix=''): """Returns a NOTICE to recipient with the message msg.""" - assert (isChannel(recipient) or isNick(recipient)), repr(recipient) - assert msg, 'msg must not be empty.' + if conf.strictRfc: + assert (isChannel(recipient) or isNick(recipient)), repr(recipient) + assert msg, 'msg must not be empty.' return IrcMsg(prefix=prefix, command='NOTICE', args=(recipient, msg)) def join(channel, key=None, prefix=''): """Returns a JOIN to a channel""" - assert isChannel(channel), repr(channel) + if conf.strictRfc: + assert isChannel(channel), repr(channel) if key is None: return IrcMsg(prefix=prefix, command='JOIN', args=(channel,)) else: - assert key.translate(string.ascii, string.ascii[128:]) == key and \ - '\x00' not in key and \ - '\r' not in key and \ - '\n' not in key and \ - '\f' not in key and \ - '\t' not in key and \ - '\v' not in key and \ - ' ' not in key - return IrcMsg(prefix=prefix, command='JOIN', args=(channel, key)) - -def joins(channels, keys=None, prefix=''): - """Returns a JOIN to each of channels.""" - assert all(isChannel, channels), channels - if keys is None: - keys = [] - assert len(keys) <= len(channels) - if not keys: - return IrcMsg(prefix=prefix, - command='JOIN', - args=(','.join(channels),)) - else: - for key in keys: + if conf.strictRfc: assert key.translate(string.ascii, string.ascii[128:]) == key and \ '\x00' not in key and \ '\r' not in key and \ @@ -481,13 +485,38 @@ def joins(channels, keys=None, prefix=''): '\t' not in key and \ '\v' not in key and \ ' ' not in key + return IrcMsg(prefix=prefix, command='JOIN', args=(channel, key)) + +def joins(channels, keys=None, prefix=''): + """Returns a JOIN to each of channels.""" + if conf.strictRfc: + assert all(isChannel, channels), channels + if keys is None: + keys = [] + assert len(keys) <= len(channels), 'Got more keys than channels.' + if not keys: + return IrcMsg(prefix=prefix, + command='JOIN', + args=(','.join(channels),)) + else: + for key in keys: + if conf.strictRfc: + assert key.translate(string.ascii,string.ascii[128:])==key and\ + '\x00' not in key and \ + '\r' not in key and \ + '\n' not in key and \ + '\f' not in key and \ + '\t' not in key and \ + '\v' not in key and \ + ' ' not in key return IrcMsg(prefix=prefix, command='JOIN', args=(','.join(channels), ','.join(keys))) def part(channel, msg='', prefix=''): """Returns a PART from channel with the message msg.""" - assert isChannel(channel), repr(channel) + if conf.strictRfc: + assert isChannel(channel), repr(channel) if msg: return IrcMsg(prefix=prefix, command='PART', args=(channel, msg)) else: @@ -495,7 +524,8 @@ def part(channel, msg='', prefix=''): def parts(channels, msg='', prefix=''): """Returns a PART from each of channels with the message msg.""" - assert all(isChannel, channels), channels + if conf.strictRfc: + assert all(isChannel, channels), channels if msg: return IrcMsg(prefix=prefix, command='PART', args=(','.join(channels), msg,)) @@ -512,7 +542,8 @@ def quit(msg='', prefix=''): def topic(channel, topic=None, prefix=''): """Returns a TOPIC for channel with the topic topic.""" - assert isChannel(channel), repr(channel) + if conf.strictRfc: + assert isChannel(channel), repr(channel) if topic is None: return IrcMsg(prefix=prefix, command='TOPIC', args=(channel,)) else: @@ -520,27 +551,31 @@ def topic(channel, topic=None, prefix=''): def nick(nick, prefix=''): """Returns a NICK with nick nick.""" - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command='NICK', args=(nick,)) def user(ident, user, prefix=''): """Returns a USER with ident ident and user user.""" - assert '\x00' not in ident and \ - '\r' not in ident and \ - '\n' not in ident and \ - ' ' not in ident and \ - '@' not in ident + if conf.strictRfc: + assert '\x00' not in ident and \ + '\r' not in ident and \ + '\n' not in ident and \ + ' ' not in ident and \ + '@' not in ident return IrcMsg(prefix=prefix, command='USER', args=(ident, '0', '*', user)) def who(hostmaskOrChannel, prefix=''): """Returns a WHO for the hostmask or channel hostmaskOrChannel.""" - assert isChannel(hostmaskOrChannel) or isUserHostmask(hostmaskOrChannel), \ - repr(hostmaskOrChannel) + if conf.strictRfc: + assert isChannel(hostmaskOrChannel) or \ + isUserHostmask(hostmaskOrChannel), repr(hostmaskOrChannel) return IrcMsg(prefix=prefix, command='WHO', args=(hostmaskOrChannel,)) def whois(nick, mask='', prefix=''): """Returns a WHOIS for nick.""" - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command='WHOIS', args=(nick, mask)) def mode(channel, args=None, prefix=''): @@ -552,12 +587,14 @@ def mode(channel, args=None, prefix=''): def invite(nick, channel, prefix=''): """Returns an INVITE for nick.""" - assert isNick(nick), repr(nick) + if conf.strictRfc: + assert isNick(nick), repr(nick) return IrcMsg(prefix=prefix, command='INVITE', args=(nick, channel)) def password(password, prefix=''): """Returns a PASS command for accessing a server.""" - assert password, 'password must not be empty.' + if conf.strictRfc: + assert password, 'password must not be empty.' return IrcMsg(prefix=prefix, command='PASS', args=(password,)) # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: diff --git a/src/ircutils.py b/src/ircutils.py index a5c3cf161..3f5ce53f0 100644 --- a/src/ircutils.py +++ b/src/ircutils.py @@ -54,12 +54,6 @@ from cStringIO import StringIO as sio import utils -### -# strictRfc: Determines whether the bot will very strictly follow the RCE -# or whether it will allow things like @ and . in nicks. -### -strictRfc = False - def isUserHostmask(s): """Returns whether or not the string s is a valid User hostmask.""" p1 = s.find('!') @@ -112,18 +106,12 @@ def nickEqual(nick1, nick2): _nickchars = r'_[]\`^{}|-' -strictNickRe = re.compile(r'^[A-Za-z%s][0-9A-Za-z%s]*$' - % (re.escape(_nickchars), re.escape(_nickchars))) -_nickchars += '@.' nickRe = re.compile(r'^[A-Za-z%s][0-9A-Za-z%s]*$' % (re.escape(_nickchars), re.escape(_nickchars))) def isNick(s): """Returns True if s is a valid IRC nick.""" - if strictRfc: - return bool(strictNickRe.match(s)) - else: - return bool(nickRe.match(s)) + return bool(nickRe.match(s)) def isChannel(s): """Returns True if s is a valid IRC channel name."""