aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar jesopo2018-09-11 08:52:12 +0100
committerGravatar jesopo2018-09-11 08:52:12 +0100
commit6c8399fa0fdcc42516cf72c0cfe78791b2ae93c7 (patch)
treea4c1809e92fd80086a2fce51e0a0dce91b81f70c
parentPass around an IRCPrefix object instead of "nickname!username@hostname", fix a (diff)
signature
Respect RFC1459 casemapping rules
-rw-r--r--IRCBuffer.py5
-rw-r--r--IRCChannel.py4
-rw-r--r--IRCLineHandler.py11
-rw-r--r--IRCServer.py19
-rw-r--r--IRCUser.py4
-rw-r--r--Utils.py19
6 files changed, 45 insertions, 17 deletions
diff --git a/IRCBuffer.py b/IRCBuffer.py
index 6e689d30..619f9061 100644
--- a/IRCBuffer.py
+++ b/IRCBuffer.py
@@ -1,4 +1,5 @@
import re
+import Utils
class BufferLine(object):
def __init__(self, sender, message, action, from_self):
@@ -28,7 +29,7 @@ class Buffer(object):
def find(self, pattern, **kwargs):
from_self = kwargs.get("from_self", True)
for_user = kwargs.get("for_user", "")
- for_user = for_user.lower() if for_user else None
+ for_user = Utils.irc_lower(for_user) if for_user else None
not_pattern = kwargs.get("not_pattern", None)
for line in self.lines:
if line.from_self and not from_self:
@@ -36,7 +37,7 @@ class Buffer(object):
elif re.search(pattern, line.message):
if not_pattern and re.search(not_pattern, line.message):
continue
- if for_user and not line.sender.lower() == for_user:
+ if for_user and not Utils.irc_lower(line.sender) == for_user:
continue
return line
def skip_next(self):
diff --git a/IRCChannel.py b/IRCChannel.py
index 0dfd6884..00407772 100644
--- a/IRCChannel.py
+++ b/IRCChannel.py
@@ -1,9 +1,9 @@
import uuid
-import IRCBuffer
+import IRCBuffer, Utils
class Channel(object):
def __init__(self, name, id, server, bot):
- self.name = name.lower()
+ self.name = Utils.irc_lower(name)
self.id = id
self.server = server
self.bot = bot
diff --git a/IRCLineHandler.py b/IRCLineHandler.py
index 4a19082c..d7d47f54 100644
--- a/IRCLineHandler.py
+++ b/IRCLineHandler.py
@@ -5,6 +5,7 @@ RE_PREFIXES = re.compile(r"\bPREFIX=\((\w+)\)(\W+)(?:\b|$)")
RE_CHANMODES = re.compile(
r"\bCHANMODES=(\w*),(\w*),(\w*),(\w*)(?:\b|$)")
RE_CHANTYPES = re.compile(r"\bCHANTYPES=(\W+)(?:\b|$)")
+RE_CASEMAPPING = re.compile(r"\bCASEMAPPING=(\S+)")
RE_MODES = re.compile(r"[-+]\w+")
CAPABILITIES = {"multi-prefix", "chghost", "invite-notify", "account-tag",
@@ -136,6 +137,11 @@ class LineHandler(object):
match = re.search(RE_CHANTYPES, isupport_line)
if match:
event["server"].channel_types = list(match.group(1))
+
+ match = re.search(RE_CASEMAPPING, isupport_line)
+ if match:
+ event["server"].case_mapping = match.group(1)
+
self.events.on("received.numeric.005").call(
isupport=isupport_line, server=event["server"])
@@ -554,10 +560,11 @@ class LineHandler(object):
# we need a registered nickname for this channel
def handle_477(self, event):
- if event["args"][1].lower() in event["server"].attempted_join:
+ channel_name = Utils.irc_lower(event["args"][1])
+ if channel_name in event["server"].attempted_join:
self.bot.add_timer("rejoin", 5,
channel_name=event["args"][1],
- key=event["server"].attempted_join[event["args"][1].lower()],
+ key=event["server"].attempted_join[channel_name],
server_id=event["server"].id)
# someone's been kicked from a channel
diff --git a/IRCServer.py b/IRCServer.py
index a1e3a489..8b674711 100644
--- a/IRCServer.py
+++ b/IRCServer.py
@@ -47,6 +47,7 @@ class Server(object):
{"@": "o", "+": "v"})
self.channel_modes = []
self.channel_types = []
+ self.case_mapping = "rfc1459"
self.last_read = time.monotonic()
self.last_send = None
@@ -130,9 +131,9 @@ class Server(object):
def set_own_nickname(self, nickname):
self.nickname = nickname
- self.nickname_lower = nickname.lower()
+ self.nickname_lower = Utils.irc_lower(nickname)
def is_own_nickname(self, nickname):
- return nickname.lower() == self.nickname_lower
+ return Utils.irc_equals(nickname, self.nickname)
def add_own_mode(self, mode, arg=None):
self.own_modes[mode] = arg
@@ -145,7 +146,7 @@ class Server(object):
self.add_own_mode(mode, arg)
def has_user(self, nickname):
- return nickname.lower() in self.users
+ return Utils.irc_lower(nickname) in self.users
def get_user(self, nickname):
if not self.has_user(nickname):
user_id = self.get_user_id(nickname)
@@ -154,7 +155,7 @@ class Server(object):
user=new_user, server=self)
self.users[new_user.nickname_lower] = new_user
self.new_users.add(new_user)
- return self.users[nickname.lower()]
+ return self.users[Utils.irc_lower(nickname)]
def get_user_id(self, nickname):
self.bot.database.users.add(self.id, nickname)
return self.bot.database.users.get_id(self.id, nickname)
@@ -164,12 +165,12 @@ class Server(object):
channel.remove_user(user)
def change_user_nickname(self, old_nickname, new_nickname):
- user = self.users.pop(old_nickname.lower())
+ user = self.users.pop(Utils.irc_lower(old_nickname))
user._id = self.get_user_id(new_nickname)
- self.users[new_nickname.lower()] = user
+ self.users[Utils.irc_lower(new_nickname)] = user
def has_channel(self, channel_name):
- return channel_name[0] in self.channel_types and channel_name.lower(
- ) in self.channels
+ return channel_name[0] in self.channel_types and Utils.irc_lower(
+ channel_name) in self.channels
def get_channel(self, channel_name):
if not self.has_channel(channel_name):
channel_id = self.get_channel_id(channel_name)
@@ -178,7 +179,7 @@ class Server(object):
self.events.on("new").on("channel").call(
channel=new_channel, server=self)
self.channels[new_channel.name] = new_channel
- return self.channels[channel_name.lower()]
+ return self.channels[Utils.irc_lower(channel_name)]
def get_channel_id(self, channel_name):
self.bot.database.channels.add(self.id, channel_name)
return self.bot.database.channels.get_id(self.id, channel_name)
diff --git a/IRCUser.py b/IRCUser.py
index 1bb7ad13..d336ecf1 100644
--- a/IRCUser.py
+++ b/IRCUser.py
@@ -1,5 +1,5 @@
import uuid
-import IRCBuffer
+import IRCBuffer, Utils
class User(object):
def __init__(self, nickname, id, server, bot):
@@ -31,7 +31,7 @@ class User(object):
def set_nickname(self, nickname):
self.nickname = nickname
- self.nickname_lower = nickname.lower()
+ self.nickname_lower = Utils.irc_lower(nickname)
self.name = self.nickname_lower
def join_channel(self, channel):
self.channels.add(channel)
diff --git a/Utils.py b/Utils.py
index 0aa407d4..ac39825c 100644
--- a/Utils.py
+++ b/Utils.py
@@ -1,10 +1,14 @@
import json, re, traceback, urllib.request, urllib.parse, urllib.error, ssl
+import string
import bs4
USER_AGENT = ("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36")
REGEX_HTTP = re.compile("https?://", re.I)
+RFC1459_UPPER = r'\[]~'
+RFC1459_UPPER = r'|{}^'
+
def remove_colon(s):
if s.startswith(":"):
s = s[1:]
@@ -13,6 +17,21 @@ def remove_colon(s):
def arbitrary(s, n):
return remove_colon(" ".join(s[n:]))
+def _rfc1459_lower(s):
+ for upper, lower in zip(RFC1459_UPPER, RFC1459_LOWER):
+ s = s.replace(upper, lower)
+ return s.lower()
+def irc_lower(server, s):
+ if server.case_mapping == "ascii":
+ return s.lower()
+ elif server.case_mapping == "rfc1459":
+ return _rfc1459_lower(s)
+ else:
+ raise ValueError("unknown casemapping '%s'" % server.case_mapping)
+
+def irc_equals(server, s1, s2):
+ return irc_lower(server, s1) == irc_lower(server, s2)
+
class IRCHostmask(object):
def __init__(self, nickname, username, hostname, hostmask):
self.nickname = nickname