diff --git a/modules/permissions/__init__.py b/modules/permissions/__init__.py index 6b05dfdc..702666af 100644 --- a/modules/permissions/__init__.py +++ b/modules/permissions/__init__.py @@ -12,13 +12,19 @@ class Module(ModuleManager.BaseModule): @utils.hook("new.server") def new_server(self, event): - hostmasks = {} + event["server"]._hostmasks = {} for account, user_hostmasks in event["server"].get_all_user_settings( HOSTMASKS_SETTING): for hostmask in user_hostmasks: - hostmasks[hostmask] = account - event["server"]._hostmasks = hostmasks + self._add_hostmask(event["server"], hostmask, account) + + def _add_hostmask(self, server, hostmask, account): + server._hostmasks[hostmask] = ( + utils.irc.parse_hostmask(hostmask), account) + def _remove_hostmask(self, server, hostmask): + if hostmask in server._hostmasks: + del server._hostmasks[hostmask] def _make_salt(self): return base64.b64encode(os.urandom(64)).decode("utf8") @@ -55,9 +61,9 @@ class Module(ModuleManager.BaseModule): def _find_hostmask(self, server, user): user_hostmask = user.hostmask() - for hostmask in server._hostmasks.keys(): - if utils.irc.hostmask_match(user_hostmask, hostmask): - return (hostmask, server._hostmasks[hostmask]) + for hostmask, (hostmask_pattern, account) in server._hostmasks.items(): + if utils.irc.hostmask_match(user_hostmask, hostmask_pattern): + return (hostmask, account) def _specific_hostmask(self, server, hostmask, account): for user in server.users.values(): if utils.irc.hostmask_match(user.hostmask(), hostmask): @@ -300,7 +306,7 @@ class Module(ModuleManager.BaseModule): event["user"].set_setting(HOSTMASKS_SETTING, hostmasks) self._specific_hostmask(event["server"], hostmask, account) - event["server"]._hostmasks[hostmask] = account + self._add_hostmask(event["server"], hostmask, account) event["stdout"].write("Added %s to your hostmasks" % hostmask) elif subcommand == "remove": @@ -312,8 +318,7 @@ class Module(ModuleManager.BaseModule): event["user"].set_setting(HOSTMASKS_SETTING, hostmasks) self._specific_hostmask(event["server"], hostmask, None) - if hostmask in event["server"]._hostmasks: - del event["server"]._hostmasks[hostmask] + self._remove_hostmask(event["server"], hostmask) event["stdout"].write("Removed %s from your hostmasks" % hostmask) diff --git a/src/IRCServer.py b/src/IRCServer.py index 053a8bfa..1e069e5f 100644 --- a/src/IRCServer.py +++ b/src/IRCServer.py @@ -221,10 +221,6 @@ class Server(IRCObject.Object): def irc_equals(self, s1: str, s2: str) -> bool: return utils.irc.equals(self.case_mapping, s1, s2) - def hostmask_match(self, hostmask: str, pattern: str) -> bool: - return utils.irc.hostmask_match(self.irc_lower(hostmask), - self.irc_lower(pattern)) - def _post_read(self, lines: typing.List[str]): for line in lines: self.bot.log.debug("%s (raw recv) | %s", [str(self), line]) diff --git a/src/utils/irc.py b/src/utils/irc.py index 64c0fd1c..153d6405 100644 --- a/src/utils/irc.py +++ b/src/utils/irc.py @@ -1,4 +1,4 @@ -import json, string, re, typing, uuid +import dataclasses, json, string, re, typing, uuid from . import consts ASCII_UPPER = string.ascii_uppercase @@ -262,19 +262,28 @@ class BatchType(object): t = list(set([type])&self._names) return t[0] if t else None -def hostmask_match_many(hostmasks: typing.List[str], pattern: str - ) -> typing.Optional[str]: +@dataclasses.dataclass +class HostmaskPattern(object): + original: str + pattern: typing.Pattern + + def match(self, hostmask: str): + return bool(self.pattern.fullmatch(hostmask)) +def hostmask_parse(hostmask: str): part1_out = [] - for part1 in pattern.split("?"): + for part1 in hostmask.split("?"): part2_out = [] for part2 in part1.split("*"): part2_out.append(re.escape(part2)) part1_out.append(".*".join(part2_out)) - pattern_re = re.compile(".".join(part1_out)) + return HostmaskPattern(hostmask, re.compile(".".join(part1_out))) + +def hostmask_match_many(hostmasks: typing.List[str], pattern: HostmaskPattern, + ) -> typing.Optional[str]: for hostmask in hostmasks: - if pattern_re.match(hostmask): + if pattern.match(hostmask): return hostmask return None -def hostmask_match(hostmask: str, pattern: str) -> bool: +def hostmask_match(hostmask: str, pattern: HostmaskPattern) -> bool: return not hostmask_match_many([hostmask], pattern) == None