Partly stitch up command protection.

- Never skip undoing changes. This is necessary to also process commands
that are not registered or that are fall-back aliases.
- Check adding all plugin commands always.
- Check for aliases as well for decision if to match a command.
This commit is contained in:
asofold 2014-04-15 22:31:53 +02:00
parent 547dfc890b
commit b8fd9da08f
2 changed files with 106 additions and 66 deletions

View File

@ -24,57 +24,63 @@ public class CommandUtil {
* Return plugin + server commands [Subject to change]. * Return plugin + server commands [Subject to change].
* @return Returns null if not CraftBukkit or CommandMap not available. * @return Returns null if not CraftBukkit or CommandMap not available.
*/ */
public static CommandMap getCommandMap(){ public static CommandMap getCommandMap() {
// TODO: compat / null try {
try{
return NCPAPIProvider.getNoCheatPlusAPI().getMCAccess().getCommandMap(); return NCPAPIProvider.getNoCheatPlusAPI().getMCAccess().getCommandMap();
} }
catch(Throwable t){ catch (Throwable t) {
LogUtil.logSevere(t); LogUtil.logSevere(t);
return null; return null;
} }
} }
/** /**
* Fails with an exception if SimpleCommandMap is not found, currently. * Get all Command instances, that NCP can get hold of. Attempt to get a SimpleCommandMap instance from the server to get the actually registered commands, but also get commands from JavaPlugin instances.
* @return * @return
*/ */
public static Collection<Command> getCommands(){ public static Collection<Command> getCommands() {
CommandMap commandMap = getCommandMap(); final Collection<Command> commands = new LinkedHashSet<Command>(500);
if (commandMap != null && commandMap instanceof SimpleCommandMap){
return ((SimpleCommandMap) commandMap).getCommands(); // All (?) commands from the SimpleCommandMap of the server, if available.
final CommandMap commandMap = getCommandMap();
if (commandMap != null && commandMap instanceof SimpleCommandMap) {
commands.addAll(((SimpleCommandMap) commandMap).getCommands());
} }
else{ // TODO: Fall-back for Vanilla / CB commands? [Fall-back should be altering permission defaults, though negating permissions is the right way.]
final Collection<Command> commands = new LinkedHashSet<Command>(100);
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()){ // Fall-back: plugin commands.
if (plugin instanceof JavaPlugin){ for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
final JavaPlugin javaPlugin = (JavaPlugin) plugin; if (plugin instanceof JavaPlugin) {
final Map<String, Map<String, Object>> map = javaPlugin.getDescription().getCommands(); final JavaPlugin javaPlugin = (JavaPlugin) plugin;
if (map != null){ final Map<String, Map<String, Object>> map = javaPlugin.getDescription().getCommands();
for (String label : map.keySet()){ if (map != null) {
Command command = javaPlugin.getCommand(label); for (String label : map.keySet()) {
if (command != null) commands.add(command); Command command = javaPlugin.getCommand(label);
if (command != null) {
commands.add(command);
} }
} }
} }
} }
// TODO: Vanilla / CB commands !?
return commands;
} }
return commands;
} }
/** /**
* Get the command label (trim + lower case), include server commands [subject to change]. * Get the command label (trim + lower case), include server commands [subject to change].
* @param alias * @param alias
* @param strict If to return null if no command is found. * @param strict If to return null if no command is found.
* @return * @return The command label, if possible to find, or the alias itself (+ trim + lower-case).
*/ */
public static String getCommandLabel(final String alias, final boolean strict){ public static String getCommandLabel(final String alias, final boolean strict) {
final Command command = getCommand(alias); final Command command = getCommand(alias);
if (command == null){ if (command == null) {
return strict ? null : alias.trim().toLowerCase(); return strict ? null : alias.trim().toLowerCase();
} }
else return command.getLabel().trim().toLowerCase(); else {
return command.getLabel().trim().toLowerCase();
}
} }
/** /**
@ -85,7 +91,7 @@ public class CommandUtil {
public static Command getCommand(final String alias) { public static Command getCommand(final String alias) {
final String lcAlias = alias.trim().toLowerCase(); final String lcAlias = alias.trim().toLowerCase();
final CommandMap map = getCommandMap(); final CommandMap map = getCommandMap();
if (map != null){ if (map != null) {
return map.getCommand(lcAlias); return map.getCommand(lcAlias);
} else { } else {
// TODO: maybe match versus plugin commands. // TODO: maybe match versus plugin commands.
@ -101,18 +107,22 @@ public class CommandUtil {
public static List<String> getCheckTypeTabMatches(final String input) { public static List<String> getCheckTypeTabMatches(final String input) {
final String ref = input.toUpperCase().replace('-', '_').replace('.', '_'); final String ref = input.toUpperCase().replace('-', '_').replace('.', '_');
final List<String> res = new ArrayList<String>(); final List<String> res = new ArrayList<String>();
for (final CheckType checkType : CheckType.values()){ for (final CheckType checkType : CheckType.values()) {
final String name = checkType.name(); final String name = checkType.name();
if (name.startsWith(ref)) res.add(name); if (name.startsWith(ref)) {
} res.add(name);
if (ref.indexOf('_') == -1){
for (final CheckType checkType : CheckType.values()){
final String name = checkType.name();
final String[] split = name.split("_", 2);
if (split.length > 1 && split[1].startsWith(ref)) res.add(name);
} }
} }
if (!res.isEmpty()){ if (ref.indexOf('_') == -1) {
for (final CheckType checkType : CheckType.values()) {
final String name = checkType.name();
final String[] split = name.split("_", 2);
if (split.length > 1 && split[1].startsWith(ref)) {
res.add(name);
}
}
}
if (!res.isEmpty()) {
Collections.sort(res); Collections.sort(res);
return res; return res;
} }

View File

@ -38,7 +38,7 @@ public class PermissionUtil {
* @param permissionDefault * @param permissionDefault
* @param permissionMessage * @param permissionMessage
*/ */
public CommandProtectionEntry(Command command, String label, String permission, PermissionDefault permissionDefault, String permissionMessage){ public CommandProtectionEntry(Command command, String label, String permission, PermissionDefault permissionDefault, String permissionMessage) {
this.command = command; this.command = command;
this.label = label; this.label = label;
this.permission = permission; this.permission = permission;
@ -46,14 +46,19 @@ public class PermissionUtil {
this.permissionMessage = permissionMessage; this.permissionMessage = permissionMessage;
} }
public void restore(){ public void restore() {
Command registered = CommandUtil.getCommand(label); // (Don't skip resetting, as there could be fall-back aliases.)
if (registered == null || registered != command) return; // Command registered = CommandUtil.getCommand(label);
if (!label.equalsIgnoreCase(command.getLabel().trim().toLowerCase())) command.setLabel(label); // if (registered == null || registered != command) return;
if (!label.equalsIgnoreCase(command.getLabel().trim().toLowerCase())) {
command.setLabel(label);
}
command.setPermission(permission); command.setPermission(permission);
if (permission != null && permissionDefault != null){ if (permission != null && permissionDefault != null) {
Permission perm = Bukkit.getPluginManager().getPermission(permission); Permission perm = Bukkit.getPluginManager().getPermission(permission);
if (perm != null) perm.setDefault(permissionDefault); if (perm != null && perm.getDefault() != permissionDefault) {
perm.setDefault(permissionDefault);
}
} }
command.setPermissionMessage(permissionMessage); command.setPermissionMessage(permissionMessage);
} }
@ -61,12 +66,12 @@ public class PermissionUtil {
/** /**
* *
* @param commands * @param commands Command white-list.
* @param permissionBase * @param permissionBase
* @param ops * @param ops
* @return * @return
*/ */
public static List<CommandProtectionEntry> protectCommands(Collection<String> commands, String permissionBase, boolean ops){ public static List<CommandProtectionEntry> protectCommands(Collection<String> commands, String permissionBase, boolean ops) {
return protectCommands(permissionBase, commands, true, ops); return protectCommands(permissionBase, commands, true, ops);
} }
@ -78,7 +83,7 @@ public class PermissionUtil {
* @param ops * @param ops
* @return * @return
*/ */
public static List<CommandProtectionEntry> protectCommands(String permissionBase, Collection<String> ignoredCommands, boolean invertIgnored, boolean ops){ public static List<CommandProtectionEntry> protectCommands(String permissionBase, Collection<String> ignoredCommands, boolean invertIgnored, boolean ops) {
return protectCommands(permissionBase, ignoredCommands, invertIgnored, ops, ColorUtil.replaceColors(ConfigManager.getConfigFile().getString(ConfPaths.PROTECT_PLUGINS_HIDE_NOCOMMAND_MSG))); return protectCommands(permissionBase, ignoredCommands, invertIgnored, ops, ColorUtil.replaceColors(ConfigManager.getConfigFile().getString(ConfPaths.PROTECT_PLUGINS_HIDE_NOCOMMAND_MSG)));
} }
@ -91,30 +96,33 @@ public class PermissionUtil {
* @param permissionMessage * @param permissionMessage
* @return * @return
*/ */
public static List<CommandProtectionEntry> protectCommands(String permissionBase, Collection<String> ignoredCommands, boolean invertIgnored, boolean ops, String permissionMessage){ public static List<CommandProtectionEntry> protectCommands(final String permissionBase, final Collection<String> ignoredCommands, final boolean invertIgnored, final boolean ops, final String permissionMessage) {
Set<String> checked = new HashSet<String>(); final Set<String> checked = new HashSet<String>();
for (String label : ignoredCommands){ for (String label : ignoredCommands) {
checked.add(CommandUtil.getCommandLabel(label, false)); checked.add(CommandUtil.getCommandLabel(label, false));
} }
PluginManager pm = Bukkit.getPluginManager(); final PluginManager pm = Bukkit.getPluginManager();
Permission rootPerm = pm.getPermission(permissionBase); Permission rootPerm = pm.getPermission(permissionBase);
if (rootPerm == null){ if (rootPerm == null) {
rootPerm = new Permission(permissionBase); rootPerm = new Permission(permissionBase);
pm.addPermission(rootPerm); pm.addPermission(rootPerm);
} }
List<CommandProtectionEntry> changed = new LinkedList<CommandProtectionEntry>(); final List<CommandProtectionEntry> changed = new LinkedList<CommandProtectionEntry>();
for (Command command : CommandUtil.getCommands()){ // Apply protection based on white-list or black-list.
String lcLabel = command.getLabel().trim().toLowerCase(); for (final Command command : CommandUtil.getCommands()) {
if (checked != null){ final String lcLabel = command.getLabel().trim().toLowerCase();
if (checked.contains(lcLabel)){ if (checked.contains(lcLabel) || containsAnyAliases(checked, command)) {
if (!invertIgnored) continue; if (!invertIgnored) {
continue;
} }
else if (invertIgnored) continue; }
else if (invertIgnored) {
continue;
} }
// Set the permission for the command. // Set the permission for the command.
String cmdPermName = command.getPermission(); String cmdPermName = command.getPermission();
boolean cmdHadPerm; boolean cmdHadPerm;
if (cmdPermName == null){ if (cmdPermName == null) {
// Set a permission. // Set a permission.
cmdPermName = permissionBase + "." + lcLabel; cmdPermName = permissionBase + "." + lcLabel;
command.setPermission(cmdPermName); command.setPermission(cmdPermName);
@ -125,16 +133,20 @@ public class PermissionUtil {
} }
// Set permission default behavior. // Set permission default behavior.
Permission cmdPerm = pm.getPermission(cmdPermName); Permission cmdPerm = pm.getPermission(cmdPermName);
if (cmdPerm == null){ if (cmdPerm == null) {
if (!cmdHadPerm){ if (!cmdHadPerm) {
cmdPerm = new Permission(cmdPermName); cmdPerm = new Permission(cmdPermName);
cmdPerm.addParent(rootPerm, true); cmdPerm.addParent(rootPerm, true);
pm.addPermission(cmdPerm); pm.addPermission(cmdPerm);
} }
} }
// Create change history entry. // Create change history entry.
if (cmdHadPerm) changed.add(new CommandProtectionEntry(command, lcLabel, cmdPermName, cmdPerm.getDefault(), command.getPermissionMessage())); if (cmdHadPerm) {
else changed.add(new CommandProtectionEntry(command, lcLabel, null, null, command.getPermissionMessage())); changed.add(new CommandProtectionEntry(command, lcLabel, cmdPermName, cmdPerm.getDefault(), command.getPermissionMessage()));
}
else {
changed.add(new CommandProtectionEntry(command, lcLabel, null, null, command.getPermissionMessage()));
}
// Change // Change
cmdPerm.setDefault(ops ? PermissionDefault.OP : PermissionDefault.FALSE); cmdPerm.setDefault(ops ? PermissionDefault.OP : PermissionDefault.FALSE);
command.setPermissionMessage(permissionMessage); command.setPermissionMessage(permissionMessage);
@ -142,6 +154,24 @@ public class PermissionUtil {
return changed; return changed;
} }
/**
* Check if the checked set contains any trim+lower-case alias of the command.
* @param checked
* @param command
* @return
*/
private static final boolean containsAnyAliases(final Set<String> checked, final Command command) {
final Collection<String> aliases = command.getAliases();
if (aliases != null) {
for (final String alias : aliases) {
if (checked.contains(alias.trim().toLowerCase())) {
return true;
}
}
}
return false;
}
/** /**
* Set a permission as child for all the other permissions given in a Collection. * Set a permission as child for all the other permissions given in a Collection.
* @param permissions Not expected to exist. * @param permissions Not expected to exist.
@ -150,17 +180,17 @@ public class PermissionUtil {
public static void addChildPermission(final Collection<String> permissions, final String childPermissionName, final PermissionDefault permissionDefault) { public static void addChildPermission(final Collection<String> permissions, final String childPermissionName, final PermissionDefault permissionDefault) {
final PluginManager pm = Bukkit.getPluginManager(); final PluginManager pm = Bukkit.getPluginManager();
Permission childPermission = pm.getPermission(childPermissionName); Permission childPermission = pm.getPermission(childPermissionName);
if (childPermission == null){ if (childPermission == null) {
childPermission = new Permission(childPermissionName, "auto-generated child permission (NoCheatPlus)", permissionDefault); childPermission = new Permission(childPermissionName, "auto-generated child permission (NoCheatPlus)", permissionDefault);
pm.addPermission(childPermission); pm.addPermission(childPermission);
} }
for (final String permissionName : permissions){ for (final String permissionName : permissions) {
Permission permission = pm.getPermission(permissionName); Permission permission = pm.getPermission(permissionName);
if (permission == null){ if (permission == null) {
permission = new Permission(permissionName, "auto-generated permission (NoCheatPlus)", permissionDefault); permission = new Permission(permissionName, "auto-generated permission (NoCheatPlus)", permissionDefault);
pm.addPermission(permission); pm.addPermission(permission);
} }
if (!permission.getChildren().containsKey(childPermissionName)){ if (!permission.getChildren().containsKey(childPermissionName)) {
childPermission.addParent(permission, true); childPermission.addParent(permission, true);
} }
} }