Untested, but wouldn't affect anyone who wasn't already messed up

This commit is contained in:
Aikar
2017-05-05 19:33:03 -04:00
parent 2ec1ed7c3a
commit 30f6b63308
2 changed files with 84 additions and 3 deletions
@@ -45,7 +45,6 @@ final class ACFPatterns {
public static final Pattern INTEGER = Pattern.compile("^[0-9]+$");
public static final Pattern VALID_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]{2,16}$");
public static final Pattern NON_PRINTABLE_CHARACTERS = Pattern.compile("[^\\x20-\\x7F]");
public static final Pattern EQUALS = Pattern.compile("=");
@@ -25,9 +25,12 @@ package co.aikar.commands;
import co.aikar.timings.lib.TimingManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.command.Command;
import org.bukkit.command.CommandException;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -59,9 +62,13 @@ public class BukkitCommandManager extends CommandManager {
Method getCommandMap = server.getClass().getDeclaredMethod("getCommandMap");
getCommandMap.setAccessible(true);
commandMap = (CommandMap) getCommandMap.invoke(server);
if (!commandMap.getClass().equals(SimpleCommandMap.class)) {
if (!SimpleCommandMap.class.isAssignableFrom(commandMap.getClass())) {
ACFLog.severe("ERROR: CommandMap has been hijacked! Offending command map is located at: " + commandMap.getClass().getName());
ACFLog.severe("Commands are most likely broken unless the hijacker did it in a friendly way.");
ACFLog.severe("We are going to try to hijack it back and resolve this, but you are now in dangerous territory.");
ACFLog.severe("We can not guarantee things are going to work.");
Field cmField = server.getClass().getDeclaredField("commandMap");
cmField.set(server, new ProxyCommandMap(commandMap));
ACFLog.info("Injected Proxy Command Map... good luck...");
}
Field knownCommands = commandMap.getClass().getDeclaredField("knownCommands");
knownCommands.setAccessible(true);
@@ -154,4 +161,79 @@ public class BukkitCommandManager extends CommandManager {
public TimingManager getTimings() {
return timingManager;
}
class ProxyCommandMap extends SimpleCommandMap {
CommandMap proxied;
ProxyCommandMap(CommandMap proxied) {
super(Bukkit.getServer());
this.proxied = proxied;
}
@Override
public void registerAll(String fallbackPrefix, List<Command> commands) {
proxied.registerAll(fallbackPrefix, commands);
}
@Override
public boolean register(String label, String fallbackPrefix, Command command) {
if (isOurCommand(command)) {
return super.register(label, fallbackPrefix, command);
} else {
return proxied.register(label, fallbackPrefix, command);
}
}
boolean isOurCommand(String cmdLine) {
String[] args = ACFPatterns.SPACE.split(cmdLine);
return args.length != 0 && isOurCommand(knownCommands.get(args[0].toLowerCase(Locale.ENGLISH)));
}
boolean isOurCommand(Command command) {
return command instanceof BaseCommand && ((BaseCommand) command).manager == BukkitCommandManager.this;
}
@Override
public boolean register(String fallbackPrefix, Command command) {
if (isOurCommand(command)) {
return super.register(fallbackPrefix, command);
} else {
return proxied.register(fallbackPrefix, command);
}
}
@Override
public boolean dispatch(CommandSender sender, String cmdLine) throws CommandException {
if (isOurCommand(cmdLine)) {
return super.dispatch(sender, cmdLine);
} else {
return proxied.dispatch(sender, cmdLine);
}
}
@Override
public void clearCommands() {
super.clearCommands();;
proxied.clearCommands();
}
@Override
public Command getCommand(String name) {
if (isOurCommand(name)) {
return super.getCommand(name);
} else {
return proxied.getCommand(name);
}
}
@Override
public List<String> tabComplete(CommandSender sender, String cmdLine) throws IllegalArgumentException {
if (isOurCommand(cmdLine)) {
return super.tabComplete(sender, cmdLine);
} else {
return proxied.tabComplete(sender, cmdLine);
}
}
}
}