Fixed bug with duplicate hostmasks.

This commit is contained in:
Jeremy Fincher 2004-10-09 04:57:16 +00:00
parent afa182ab7c
commit b2fbbef197
1 changed files with 44 additions and 33 deletions

View File

@ -464,44 +464,50 @@ class IrcUserCreator(Creator):
raise ValueError, 'Unexpected user command on line %s.' % lineno raise ValueError, 'Unexpected user command on line %s.' % lineno
IrcUserCreator.id = int(rest) IrcUserCreator.id = int(rest)
def name(self, rest, lineno): def _checkId(self):
if self.id is None: if self.id is None:
raise ValueError, 'Unexpected user description without id.' raise ValueError, 'Unexpected user description without user.'
def name(self, rest, lineno):
self._checkId()
self.u.name = rest self.u.name = rest
def ignore(self, rest, lineno): def ignore(self, rest, lineno):
if self.id is None: self._checkId()
raise ValueError, 'Unexpected user description without id.'
self.u.ignore = bool(eval(rest)) self.u.ignore = bool(eval(rest))
def secure(self, rest, lineno): def secure(self, rest, lineno):
if self.id is None: self._checkId()
raise ValueError, 'Unexpected user description without id.'
self.u.secure = bool(eval(rest)) self.u.secure = bool(eval(rest))
def hashed(self, rest, lineno): def hashed(self, rest, lineno):
if self.id is None: self._checkId()
raise ValueError, 'Unexpected user description without id.'
self.u.hashed = bool(eval(rest)) self.u.hashed = bool(eval(rest))
def password(self, rest, lineno): def password(self, rest, lineno):
if self.id is None: self._checkId()
raise ValueError, 'Unexpected user description without id.'
self.u.password = rest self.u.password = rest
def hostmask(self, rest, lineno): def hostmask(self, rest, lineno):
if self.id is None: self._checkId()
raise ValueError, 'Unexpected user description without id.'
self.u.hostmasks.append(rest) self.u.hostmasks.append(rest)
def capability(self, rest, lineno): def capability(self, rest, lineno):
if self.id is None: self._checkId()
raise ValueError, 'Unexpected user description without id.'
self.u.capabilities.add(rest) self.u.capabilities.add(rest)
def finish(self): def finish(self):
if self.u.name: if self.u.name:
self.users.setUser(self.id, self.u) try:
self.users.setUser(self.id, self.u)
except DuplicateHostmask:
log.error('Hostmasks for %s collided with another user\'s. '
'Resetting hostmasks for %s.', self.u.name)
# Some might argue that this is arbitrary, and perhaps it is.
# But we've got to do *something*, so we'll show some deference
# to our lower-numbered users.
self.u.hostmasks[:] = []
self.users.setUser(self.id, self.u)
IrcUserCreator.id = None IrcUserCreator.id = None
class IrcChannelCreator(Creator): class IrcChannelCreator(Creator):
@ -516,30 +522,29 @@ class IrcChannelCreator(Creator):
raise ValueError, 'Unexpected channel command on line %s' % lineno raise ValueError, 'Unexpected channel command on line %s' % lineno
IrcChannelCreator.name = rest IrcChannelCreator.name = rest
def lobotomized(self, rest, lineno): def _checkId(self):
if self.name is None: if self.name is None:
raise ValueError, 'Unexpected channel description without channel.' raise ValueError, 'Unexpected channel description without channel.'
def lobotomized(self, rest, lineno):
self._checkId()
self.c.lobotomized = bool(eval(rest)) self.c.lobotomized = bool(eval(rest))
def defaultallow(self, rest, lineno): def defaultallow(self, rest, lineno):
if self.name is None: self._checkId()
raise ValueError, 'Unexpected channel description without channel.'
self.c.defaultAllow = bool(eval(rest)) self.c.defaultAllow = bool(eval(rest))
def capability(self, rest, lineno): def capability(self, rest, lineno):
if self.name is None: self._checkId()
raise ValueError, 'Unexpected channel description without channel.'
self.c.capabilities.add(rest) self.c.capabilities.add(rest)
def ban(self, rest, lineno): def ban(self, rest, lineno):
if self.name is None: self._checkId()
raise ValueError, 'Unexpected channel description without channel.'
(pattern, expiration) = rest (pattern, expiration) = rest
self.c.bans[pattern] = int(float(expiration)) self.c.bans[pattern] = int(float(expiration))
def ignore(self, rest, lineno): def ignore(self, rest, lineno):
if self.name is None: self._checkId()
raise ValueError, 'Unexpected channel description without channel.'
(pattern, expiration) = rest.split() (pattern, expiration) = rest.split()
self.c.ignores[pattern] = int(float(expiration)) self.c.ignores[pattern] = int(float(expiration))
@ -549,6 +554,9 @@ class IrcChannelCreator(Creator):
IrcChannelCreator.name = None IrcChannelCreator.name = None
class DuplicateHostmask(ValueError):
pass
class UsersDictionary(utils.IterableMap): class UsersDictionary(utils.IterableMap):
"""A simple serialized-to-file User Database.""" """A simple serialized-to-file User Database."""
def __init__(self): def __init__(self):
@ -644,7 +652,7 @@ class UsersDictionary(utils.IterableMap):
for (id, hostmask) in ids.iteritems(): for (id, hostmask) in ids.iteritems():
log.error('Removing %r from user %s.', hostmask, id) log.error('Removing %r from user %s.', hostmask, id)
self.users[id].removeHostmask(hostmask) self.users[id].removeHostmask(hostmask)
raise ValueError, 'Ids %r matched.' % ids raise DuplicateHostmask, 'Ids %r matched.' % ids
else: # Not a hostmask, must be a name. else: # Not a hostmask, must be a name.
s = s.lower() s = s.lower()
try: try:
@ -664,6 +672,9 @@ class UsersDictionary(utils.IterableMap):
# Must be a string. Get the UserId first. # Must be a string. Get the UserId first.
id = self.getUserId(id) id = self.getUserId(id)
u = self.users[id] u = self.users[id]
while isinstance(u, int):
id = u
u = self.users[id]
u.id = id u.id = id
return u return u
@ -703,8 +714,7 @@ class UsersDictionary(utils.IterableMap):
self.nextId = max(self.nextId, id) self.nextId = max(self.nextId, id)
try: try:
if self.getUserId(user.name) != id: if self.getUserId(user.name) != id:
s = '%s is someone else\'s hostmask.' % user.name raise DuplicateHostmask, hostmask
raise ValueError, s
except KeyError: except KeyError:
pass pass
for hostmask in user.hostmasks: for hostmask in user.hostmasks:
@ -712,14 +722,15 @@ class UsersDictionary(utils.IterableMap):
if i == id: if i == id:
continue continue
elif u.checkHostmask(hostmask): elif u.checkHostmask(hostmask):
s = '%s is someone else\'s hostmask.' % hostmask # We used to remove the hostmask here, but it's not
user.removeHostmask(hostmask) # appropriate for us both to remove the hostmask and to
raise ValueError, s # raise an exception. So instead, we'll raise an
# exception, but be nice and give the offending hostmask
# back at the same time.
raise DuplicateHostmask, hostmask
for otherHostmask in u.hostmasks: for otherHostmask in u.hostmasks:
if ircutils.hostmaskPatternEqual(hostmask, otherHostmask): if ircutils.hostmaskPatternEqual(hostmask, otherHostmask):
user.removeHostmask(hostmask) raise DuplicateHostmask, hostmask
s = '%s is someone else\'s hostmask.' % hostmask
raise ValueError, s
self.invalidateCache(id) self.invalidateCache(id)
self.users[id] = user self.users[id] = user
self.flush() self.flush()