mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-01 01:09:22 +01:00
Attempt to make sender validation in protocols a bit less repetitive
This commit is contained in:
parent
05752d9f60
commit
7003ff848d
32
classes.py
32
classes.py
@ -907,6 +907,38 @@ class Protocol():
|
|||||||
target = self.irc.nickToUid(target) or target
|
target = self.irc.nickToUid(target) or target
|
||||||
return target
|
return target
|
||||||
|
|
||||||
|
def checkSender(check):
|
||||||
|
"""
|
||||||
|
Helper function for protocols which validates that the sender given is
|
||||||
|
an internal client or server.
|
||||||
|
|
||||||
|
Check is given as a string, where 's' refers to server,
|
||||||
|
'c' refers to client, and 'cs' refers to either server or client."""
|
||||||
|
# We have to actually wrap this twice, to past checkSender('string')
|
||||||
|
# arguments to the actual function that performs checks. Gross.
|
||||||
|
def checkSender_get_check(func):
|
||||||
|
def checkSender_wrapper(self, sender, *args, **kwargs):
|
||||||
|
# 1) Perform checks.
|
||||||
|
isclient = self.irc.isInternalClient(sender)
|
||||||
|
isserver = self.irc.isInternalServer(sender)
|
||||||
|
log.debug('checkServer: query is %s, target is %s', check, sender)
|
||||||
|
log.debug('checkServer: isclient: %s, isserver: %s', isclient, isserver)
|
||||||
|
|
||||||
|
if check == 'cs':
|
||||||
|
if not (isclient or isserver):
|
||||||
|
raise LookupError('No such PyLink client/server exists.')
|
||||||
|
elif check == 'c':
|
||||||
|
if not isclient:
|
||||||
|
raise LookupError('No such PyLink client exists.')
|
||||||
|
elif check == 's':
|
||||||
|
if not isserver:
|
||||||
|
raise LookupError('No such PyLink server exists.')
|
||||||
|
|
||||||
|
# 2) Call and return the data of the original function.
|
||||||
|
return func(self, sender, *args, **kwargs)
|
||||||
|
return checkSender_wrapper
|
||||||
|
return checkSender_get_check
|
||||||
|
|
||||||
### FakeIRC classes, used for test cases
|
### FakeIRC classes, used for test cases
|
||||||
|
|
||||||
class FakeIRC(Irc):
|
class FakeIRC(Irc):
|
||||||
|
@ -71,16 +71,15 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
|||||||
self._operUp(uid, opertype)
|
self._operUp(uid, opertype)
|
||||||
return u
|
return u
|
||||||
|
|
||||||
|
@checkSender('c')
|
||||||
def join(self, client, channel):
|
def join(self, client, channel):
|
||||||
"""Joins a PyLink client to a channel."""
|
"""Joins a PyLink client to a channel."""
|
||||||
# InspIRCd doesn't distinguish between burst joins and regular joins,
|
# InspIRCd doesn't distinguish between burst joins and regular joins,
|
||||||
# so what we're actually doing here is sending FJOIN from the server,
|
# so what we're actually doing here is sending FJOIN from the server,
|
||||||
# on behalf of the clients that are joining.
|
# on behalf of the clients that are joining.
|
||||||
channel = utils.toLower(self.irc, channel)
|
channel = utils.toLower(self.irc, channel)
|
||||||
server = self.irc.isInternalClient(client)
|
server = self.irc.getServer(client)
|
||||||
if not server:
|
|
||||||
log.error('(%s) Error trying to join %r to %r (no such client exists)', self.irc.name, client, channel)
|
|
||||||
raise LookupError('No such PyLink client exists.')
|
|
||||||
# Strip out list-modes, they shouldn't be ever sent in FJOIN.
|
# Strip out list-modes, they shouldn't be ever sent in FJOIN.
|
||||||
modes = [m for m in self.irc.channels[channel].modes if m[0] not in self.irc.cmodes['*A']]
|
modes = [m for m in self.irc.channels[channel].modes if m[0] not in self.irc.cmodes['*A']]
|
||||||
self._send(server, "FJOIN {channel} {ts} {modes} :,{uid}".format(
|
self._send(server, "FJOIN {channel} {ts} {modes} :,{uid}".format(
|
||||||
@ -89,6 +88,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
|||||||
self.irc.channels[channel].users.add(client)
|
self.irc.channels[channel].users.add(client)
|
||||||
self.irc.users[client].channels.add(channel)
|
self.irc.users[client].channels.add(channel)
|
||||||
|
|
||||||
|
@checkSender('s')
|
||||||
def sjoin(self, server, channel, users, ts=None):
|
def sjoin(self, server, channel, users, ts=None):
|
||||||
"""Sends an SJOIN for a group of users to a channel.
|
"""Sends an SJOIN for a group of users to a channel.
|
||||||
|
|
||||||
@ -104,8 +104,6 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
|||||||
server = server or self.irc.sid
|
server = server or self.irc.sid
|
||||||
assert users, "sjoin: No users sent?"
|
assert users, "sjoin: No users sent?"
|
||||||
log.debug('(%s) sjoin: got %r for users', self.irc.name, users)
|
log.debug('(%s) sjoin: got %r for users', self.irc.name, users)
|
||||||
if not server:
|
|
||||||
raise LookupError('No such PyLink client exists.')
|
|
||||||
|
|
||||||
orig_ts = self.irc.channels[channel].ts
|
orig_ts = self.irc.channels[channel].ts
|
||||||
ts = ts or orig_ts
|
ts = ts or orig_ts
|
||||||
@ -163,15 +161,12 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
|||||||
userobj.opertype = otype
|
userobj.opertype = otype
|
||||||
self._send(target, 'OPERTYPE %s' % otype.replace(" ", "_"))
|
self._send(target, 'OPERTYPE %s' % otype.replace(" ", "_"))
|
||||||
|
|
||||||
|
@checkSender('cs')
|
||||||
def mode(self, numeric, target, modes, ts=None):
|
def mode(self, numeric, target, modes, ts=None):
|
||||||
"""Sends mode changes from a PyLink client/server."""
|
"""Sends mode changes from a PyLink client/server."""
|
||||||
# -> :9PYAAAAAA FMODE #pylink 1433653951 +os 9PYAAAAAA
|
# -> :9PYAAAAAA FMODE #pylink 1433653951 +os 9PYAAAAAA
|
||||||
# -> :9PYAAAAAA MODE 9PYAAAAAA -i+w
|
# -> :9PYAAAAAA MODE 9PYAAAAAA -i+w
|
||||||
|
|
||||||
if (not self.irc.isInternalClient(numeric)) and \
|
|
||||||
(not self.irc.isInternalServer(numeric)):
|
|
||||||
raise LookupError('No such PyLink client/server exists.')
|
|
||||||
|
|
||||||
log.debug('(%s) inspircd._sendModes: received %r for mode list', self.irc.name, modes)
|
log.debug('(%s) inspircd._sendModes: received %r for mode list', self.irc.name, modes)
|
||||||
if ('+o', None) in modes and not utils.isChannel(target):
|
if ('+o', None) in modes and not utils.isChannel(target):
|
||||||
# https://github.com/inspircd/inspircd/blob/master/src/modules/m_spanningtree/opertype.cpp#L26-L28
|
# https://github.com/inspircd/inspircd/blob/master/src/modules/m_spanningtree/opertype.cpp#L26-L28
|
||||||
@ -185,12 +180,9 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
|||||||
else:
|
else:
|
||||||
self._send(numeric, 'MODE %s %s' % (target, joinedmodes))
|
self._send(numeric, 'MODE %s %s' % (target, joinedmodes))
|
||||||
|
|
||||||
|
@checkSender('cs')
|
||||||
def kill(self, numeric, target, reason):
|
def kill(self, numeric, target, reason):
|
||||||
"""Sends a kill from a PyLink client/server."""
|
"""Sends a kill from a PyLink client/server."""
|
||||||
if (not self.irc.isInternalClient(numeric)) and \
|
|
||||||
(not self.irc.isInternalServer(numeric)):
|
|
||||||
raise LookupError('No such PyLink client/server exists.')
|
|
||||||
|
|
||||||
# InspIRCd will show the raw kill message sent from our server as the quit message.
|
# InspIRCd will show the raw kill message sent from our server as the quit message.
|
||||||
# So, make the kill look actually like a kill instead of someone quitting with
|
# So, make the kill look actually like a kill instead of someone quitting with
|
||||||
# an arbitrary message.
|
# an arbitrary message.
|
||||||
@ -207,22 +199,23 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
|||||||
if self.irc.isInternalClient(target):
|
if self.irc.isInternalClient(target):
|
||||||
self.removeClient(target)
|
self.removeClient(target)
|
||||||
|
|
||||||
|
@checkSender('s')
|
||||||
def topicBurst(self, numeric, target, text):
|
def topicBurst(self, numeric, target, text):
|
||||||
"""Sends a topic change from a PyLink server. This is usually used on burst."""
|
"""Sends a topic change from a PyLink server. This is usually used on burst."""
|
||||||
if not self.irc.isInternalServer(numeric):
|
|
||||||
raise LookupError('No such PyLink server exists.')
|
|
||||||
ts = int(time.time())
|
ts = int(time.time())
|
||||||
servername = self.irc.servers[numeric].name
|
servername = self.irc.servers[numeric].name
|
||||||
self._send(numeric, 'FTOPIC %s %s %s :%s' % (target, ts, servername, text))
|
self._send(numeric, 'FTOPIC %s %s %s :%s' % (target, ts, servername, text))
|
||||||
self.irc.channels[target].topic = text
|
self.irc.channels[target].topic = text
|
||||||
self.irc.channels[target].topicset = True
|
self.irc.channels[target].topicset = True
|
||||||
|
|
||||||
|
@checkSender('c')
|
||||||
def invite(self, numeric, target, channel):
|
def invite(self, numeric, target, channel):
|
||||||
"""Sends an INVITE from a PyLink client.."""
|
"""Sends an INVITE from a PyLink client.."""
|
||||||
if not self.irc.isInternalClient(numeric):
|
if not self.irc.isInternalClient(numeric):
|
||||||
raise LookupError('No such PyLink client exists.')
|
raise LookupError('No such PyLink client exists.')
|
||||||
self._send(numeric, 'INVITE %s %s' % (target, channel))
|
self._send(numeric, 'INVITE %s %s' % (target, channel))
|
||||||
|
|
||||||
|
@checkSender('c')
|
||||||
def knock(self, numeric, target, text):
|
def knock(self, numeric, target, text):
|
||||||
"""Sends a KNOCK from a PyLink client."""
|
"""Sends a KNOCK from a PyLink client."""
|
||||||
if not self.irc.isInternalClient(numeric):
|
if not self.irc.isInternalClient(numeric):
|
||||||
@ -284,7 +277,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
|||||||
"protocol module. WHOIS requests are handled "
|
"protocol module. WHOIS requests are handled "
|
||||||
"locally by InspIRCd servers, so there is no "
|
"locally by InspIRCd servers, so there is no "
|
||||||
"need for PyLink to send numerics directly yet.")
|
"need for PyLink to send numerics directly yet.")
|
||||||
|
@checkSender('c')
|
||||||
def away(self, source, text):
|
def away(self, source, text):
|
||||||
"""Sends an AWAY message from a PyLink client. <text> can be an empty string
|
"""Sends an AWAY message from a PyLink client. <text> can be an empty string
|
||||||
to unset AWAY status."""
|
to unset AWAY status."""
|
||||||
@ -334,6 +327,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
|||||||
endburstf()
|
endburstf()
|
||||||
return sid
|
return sid
|
||||||
|
|
||||||
|
@checkSender('cs')
|
||||||
def squit(self, source, target, text='No reason given'):
|
def squit(self, source, target, text='No reason given'):
|
||||||
"""SQUITs a PyLink server."""
|
"""SQUITs a PyLink server."""
|
||||||
# -> :9PY SQUIT 9PZ :blah, blah
|
# -> :9PY SQUIT 9PZ :blah, blah
|
||||||
|
Loading…
Reference in New Issue
Block a user