Limit the number of combinations of capabilities required for command names with spaces.

To call a command named 'X Y Z' in plugin 'P', we used to require lots of capabilities,
like 'P.X', 'P.Y', 'P.Z', 'P.X.Y', 'X.Y', 'P.Y', ...
Now, we only require 'P', 'P.X', 'P.X.Y', 'P.X.Y.Z', and 'Z'.

It makes it a lot easier to work with command names with a space when
supybot.capabilities.default is False.
This commit is contained in:
Valentin Lorentz 2018-02-02 18:20:05 +01:00
parent 2472e857c7
commit 636712be51

View File

@ -383,36 +383,28 @@ def formatCommand(command):
return ' '.join(command) return ' '.join(command)
def checkCommandCapability(msg, cb, commandName): def checkCommandCapability(msg, cb, commandName):
if not isinstance(commandName, minisix.string_types):
commandName = '.'.join(commandName)
plugin = cb.name().lower() plugin = cb.name().lower()
pluginCommand = '%s.%s' % (plugin, commandName) if not isinstance(commandName, minisix.string_types):
assert commandName[0] == plugin, ('checkCommandCapability no longer '
'accepts command names that do not start with the callback\'s '
'name (%s): %s') % (plugin, commandName)
commandName = '.'.join(commandName)
def checkCapability(capability): def checkCapability(capability):
assert ircdb.isAntiCapability(capability) assert ircdb.isAntiCapability(capability)
if ircdb.checkCapability(msg.prefix, capability): if ircdb.checkCapability(msg.prefix, capability):
log.info('Preventing %s from calling %s because of %s.', log.info('Preventing %s from calling %s because of %s.',
msg.prefix, pluginCommand, capability) msg.prefix, commandName, capability)
raise RuntimeError(capability) raise RuntimeError(capability)
try: try:
antiPlugin = ircdb.makeAntiCapability(plugin)
antiCommand = ircdb.makeAntiCapability(commandName) antiCommand = ircdb.makeAntiCapability(commandName)
antiPluginCommand = ircdb.makeAntiCapability(pluginCommand)
checkCapability(antiPlugin)
checkCapability(antiCommand) checkCapability(antiCommand)
checkCapability(antiPluginCommand) checkAtEnd = [commandName]
checkAtEnd = [commandName, pluginCommand]
default = conf.supybot.capabilities.default() default = conf.supybot.capabilities.default()
if ircutils.isChannel(msg.args[0]): if ircutils.isChannel(msg.args[0]):
channel = msg.args[0] channel = msg.args[0]
checkCapability(ircdb.makeChannelCapability(channel, antiCommand)) checkCapability(ircdb.makeChannelCapability(channel, antiCommand))
checkCapability(ircdb.makeChannelCapability(channel, antiPlugin))
checkCapability(ircdb.makeChannelCapability(channel,
antiPluginCommand))
chanPlugin = ircdb.makeChannelCapability(channel, plugin)
chanCommand = ircdb.makeChannelCapability(channel, commandName) chanCommand = ircdb.makeChannelCapability(channel, commandName)
chanPluginCommand = ircdb.makeChannelCapability(channel, checkAtEnd += [chanCommand]
pluginCommand)
checkAtEnd += [chanCommand, chanPlugin, chanPluginCommand]
default &= ircdb.channels.getChannel(channel).defaultAllow default &= ircdb.channels.getChannel(channel).defaultAllow
return not (default or \ return not (default or \
any(lambda x: ircdb.checkCapability(msg.prefix, x), any(lambda x: ircdb.checkCapability(msg.prefix, x),
@ -1301,18 +1293,29 @@ class Commands(BasePlugin, SynchronizedAndFirewalled):
else: else:
self.log.info('%s called on %s by %q.', formatCommand(command), self.log.info('%s called on %s by %q.', formatCommand(command),
msg.args[0], msg.prefix) msg.args[0], msg.prefix)
# XXX I'm being extra-special-careful here, but we need to refactor
# this.
try: try:
cap = checkCommandCapability(msg, self, command) if len(command) == 1 or command[0] != self.canonicalName():
fullCommandName = [self.canonicalName()] + command
else:
fullCommandName = command
# Let "P" be the plugin and "X Y" the command name. The
# fullCommandName is "P X Y"
# check "Y"
cap = checkCommandCapability(msg, self, command[-1])
if cap: if cap:
irc.errorNoCapability(cap) irc.errorNoCapability(cap)
return return
for name in command:
cap = checkCommandCapability(msg, self, name) # check "P", "P.X", and "P.X.Y"
prefix = []
for name in fullCommandName:
prefix.append(name)
cap = checkCommandCapability(msg, self, prefix)
if cap: if cap:
irc.errorNoCapability(cap) irc.errorNoCapability(cap)
return return
try: try:
self.callingCommand = command self.callingCommand = command
self.callCommand(command, irc, msg, *args, **kwargs) self.callCommand(command, irc, msg, *args, **kwargs)