Changes for command lists, opinconsoleonly -> consoleonly.

The command lists for handleaschat and exclusions are now also fed with
 a leading "/" if missing. Allows more convenient setup and less 
 confusion potential for relating comamnd lists in "protect plugins" to 
 other lists.
 
opinconsoleonly has been made a list of commands:
	protection.commands.consoleonly.
Further the message sent to the player is the permission message,
 if the player does not have permission to use the command,
 provided NCP can find the command.

All three command lists are also checked with the original 
command label.
This commit is contained in:
asofold 2013-08-11 12:36:39 +02:00
parent 86da983cf8
commit d202d73cab
5 changed files with 99 additions and 34 deletions

View File

@ -106,6 +106,20 @@ public class CharPrefixTree<N extends CharNode<N>, L extends CharLookupEntry<N>>
return false; return false;
} }
/**
* Test hasPrefixWords for each given argument.
* @param inputs
* @return true if hasPrefixWords returns ture for any of the inputs, false otherwise.
*/
public boolean hasAnyPrefixWords(final String... inputs){
for (int i = 0; i < inputs.length; i++){
if (hasPrefixWords(inputs[i])){
return true;
}
}
return false;
}
public boolean isPrefix(final char[] chars){ public boolean isPrefix(final char[] chars){
return isPrefix(toCharacterList(chars)); return isPrefix(toCharacterList(chars));
} }

View File

@ -129,7 +129,7 @@ public class ChatConfig extends AsyncCheckConfig {
public final String loginsKickMessage; public final String loginsKickMessage;
public final long loginsStartupDelay; public final long loginsStartupDelay;
public final boolean opInConsoleOnly; public final boolean consoleOnlyCheck;
public final boolean relogCheck; public final boolean relogCheck;
@ -223,7 +223,7 @@ public class ChatConfig extends AsyncCheckConfig {
relogWarningTimeout = config.getLong(ConfPaths.CHAT_RELOG_WARNING_TIMEOUT); relogWarningTimeout = config.getLong(ConfPaths.CHAT_RELOG_WARNING_TIMEOUT);
relogActions = config.getOptimizedActionList(ConfPaths.CHAT_RELOG_ACTIONS, Permissions.CHAT_RELOG); relogActions = config.getOptimizedActionList(ConfPaths.CHAT_RELOG_ACTIONS, Permissions.CHAT_RELOG);
opInConsoleOnly = config.getBoolean(ConfPaths.MISCELLANEOUS_OPINCONSOLEONLY); consoleOnlyCheck = config.getBoolean(ConfPaths.PROTECT_COMMANDS_CONSOLEONLY_ACTIVE);
} }

View File

@ -1,6 +1,9 @@
package fr.neatmonster.nocheatplus.checks.chat; package fr.neatmonster.nocheatplus.checks.chat;
import java.util.Collection;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -65,6 +68,9 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
/** Commands to be handled as chat. */ /** Commands to be handled as chat. */
private final SimpleCharPrefixTree chatCommands = new SimpleCharPrefixTree(); private final SimpleCharPrefixTree chatCommands = new SimpleCharPrefixTree();
/** Commands not to be executed in-game. */
private final SimpleCharPrefixTree consoleOnlyCommands = new SimpleCharPrefixTree();
public ChatListener(){ public ChatListener(){
super(CheckType.CHAT); super(CheckType.CHAT);
ConfigFile config = ConfigManager.getConfigFile(); ConfigFile config = ConfigManager.getConfigFile();
@ -72,11 +78,35 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
// (text inits in constructor.) // (text inits in constructor.)
} }
/**
* Clear tree and feed lower case. Add versions with "/" if missing.
* @param tree
* @param inputs
*/
private void feedCommands(SimpleCharPrefixTree tree, Collection<String> inputs){
tree.clear();
tree.feedAll(inputs, false, true);
for (String input : inputs){
if (!input.trim().startsWith("/")){
tree.feed("/" + input.trim().toLowerCase());
}
}
}
/**
* Read string list from config and call feedCommands(tree, list).
* @param tree
* @param config
* @param configPath
*/
private void feedCommands(SimpleCharPrefixTree tree, ConfigFile config, String configPath){
feedCommands(tree, config.getStringList(configPath));
}
private void initFilters(ConfigFile config) { private void initFilters(ConfigFile config) {
commandExclusions.clear(); feedCommands(consoleOnlyCommands, config, ConfPaths.PROTECT_COMMANDS_CONSOLEONLY_CMDS);
commandExclusions.feedAll(config.getStringList(ConfPaths.CHAT_COMMANDS_EXCLUSIONS), false, true); feedCommands(chatCommands, config, ConfPaths.CHAT_COMMANDS_HANDLEASCHAT);
chatCommands.clear(); feedCommands(commandExclusions, config, ConfPaths.CHAT_COMMANDS_EXCLUSIONS);
chatCommands.feedAll(config.getStringList(ConfPaths.CHAT_COMMANDS_HANDLEASCHAT), false, true);
} }
@EventHandler(priority=EventPriority.MONITOR) @EventHandler(priority=EventPriority.MONITOR)
@ -143,42 +173,53 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
// Tell TickTask to update cached permissions. // Tell TickTask to update cached permissions.
TickTask.requestPermissionUpdate(player.getName(), CheckType.CHAT); TickTask.requestPermissionUpdate(player.getName(), CheckType.CHAT);
// Trim is necessary because the server accepts leading spaces with commands.
String lcMessage = event.getMessage().trim().toLowerCase();
final String alias = lcMessage.split(" ")[0].substring(1);
final String commandLabel = CommandUtil.getCommandLabel(alias, false);
final ChatConfig cc = ChatConfig.getConfig(player); final ChatConfig cc = ChatConfig.getConfig(player);
// Prevent /op and /deop commands from being used by players. // Checks that replace parts of the message (color).
if (cc.opInConsoleOnly && (commandLabel.equals("op") || commandLabel.equals("deop"))) { if (color.isEnabled(player)){
player.sendMessage(ChatColor.RED + "I'm sorry, but this command can't be executed in chat. Use the console instead!"); event.setMessage(color.check(player, event.getMessage(), true));
event.setCancelled(true); }
return;
// Trim is necessary because the server accepts leading spaces with commands.
final String message = event.getMessage();
final String lcMessage = message.trim().toLowerCase();
final String[] split = lcMessage.split(" ", 2);
final String alias = split[0].substring(1);
final Command command = CommandUtil.getCommand(alias);
final String lcAltMessage;
if (command != null){
lcAltMessage = "/" + command.getLabel().toLowerCase() + (split.length > 1 ? (" " + split[1]) : "");
}
else{
lcAltMessage = lcMessage;
} }
// First the color check. // Prevent /op and /deop commands from being used by players.
if (color.isEnabled(player)) event.setMessage(color.check(player, event.getMessage(), true)); if (cc.consoleOnlyCheck && consoleOnlyCommands.hasAnyPrefixWords(lcMessage, lcAltMessage)) {
if (command == null || command.testPermission(player)){
player.sendMessage(ChatColor.RED + "I'm sorry, but this command can't be executed in chat. Use the console instead!");
}
event.setCancelled(true);
return;
}
// Reset lcMessage (might be canged by color check). // Handle as chat or command.
lcMessage = event.getMessage().trim().toLowerCase(); final boolean handleAsChat = chatCommands.hasAnyPrefixWords(lcMessage, lcAltMessage);
final boolean handleAsChat = chatCommands.hasPrefixWords(lcMessage);
// Then the no pwnage check.
if (handleAsChat){ if (handleAsChat){
// Treat as chat. // Treat as chat.
if (text.isEnabled(player) && text.check(player, event.getMessage(), captcha, true)) // TODO: At least cut off the command (!).
if (text.isEnabled(player) && text.check(player, message, captcha, true))
event.setCancelled(true); event.setCancelled(true);
} }
else if (!commandExclusions.hasPrefixWords(lcMessage)){ else if (!commandExclusions.hasAnyPrefixWords(lcMessage, lcAltMessage)){
// Treat as command. // Treat as command.
if (commands.isEnabled(player) && commands.check(player, event.getMessage(), captcha)) if (commands.isEnabled(player) && commands.check(player, message, captcha))
event.setCancelled(true); event.setCancelled(true);
} }
} }
/** /**
* We listen to this type of events to prevent spambots from login to the server. * We listen to this type of events to prevent spambots from login to the server.
* *
* @param event * @param event

View File

@ -70,7 +70,6 @@ public abstract class ConfPaths {
*/ */
@GlobalConfig @GlobalConfig
private static final String MISCELLANEOUS = "miscellaneous."; private static final String MISCELLANEOUS = "miscellaneous.";
public static final String MISCELLANEOUS_OPINCONSOLEONLY = MISCELLANEOUS + "opinconsoleonly";
public static final String MISCELLANEOUS_CHECKFORUPDATES = MISCELLANEOUS + "checkforupdates"; public static final String MISCELLANEOUS_CHECKFORUPDATES = MISCELLANEOUS + "checkforupdates";
public static final String MISCELLANEOUS_UPDATETIMEOUT = MISCELLANEOUS + "updatetimeout"; public static final String MISCELLANEOUS_UPDATETIMEOUT = MISCELLANEOUS + "updatetimeout";
public static final String MISCELLANEOUS_REPORTTOMETRICS = MISCELLANEOUS + "reporttometrics"; public static final String MISCELLANEOUS_REPORTTOMETRICS = MISCELLANEOUS + "reporttometrics";
@ -107,6 +106,12 @@ public abstract class ConfPaths {
private static final String PROTECT_CLIENTS_MOTD = PROTECT_CLIENTS + "motd."; private static final String PROTECT_CLIENTS_MOTD = PROTECT_CLIENTS + "motd.";
public static final String PROTECT_CLIENTS_MOTD_ACTIVE = PROTECT_CLIENTS_MOTD + "active"; public static final String PROTECT_CLIENTS_MOTD_ACTIVE = PROTECT_CLIENTS_MOTD + "active";
public static final String PROTECT_CLIENTS_MOTD_ALLOWALL = PROTECT_CLIENTS_MOTD + "allowall"; public static final String PROTECT_CLIENTS_MOTD_ALLOWALL = PROTECT_CLIENTS_MOTD + "allowall";
// Other commands settings
@GlobalConfig
private static final String PROTECT_COMMANDS = PROTECT + "commands.";
private static final String PROTECT_COMMANDS_CONSOLEONLY = PROTECT_COMMANDS + "consoleonly.";
public static final String PROTECT_COMMANDS_CONSOLEONLY_ACTIVE = PROTECT_COMMANDS_CONSOLEONLY + "active";
public static final String PROTECT_COMMANDS_CONSOLEONLY_CMDS = PROTECT_COMMANDS_CONSOLEONLY + "commands";
// Plugins settings. // Plugins settings.
private static final String PROTECT_PLUGINS = PROTECT + "plugins."; private static final String PROTECT_PLUGINS = PROTECT + "plugins.";
@GlobalConfig @GlobalConfig
@ -119,6 +124,7 @@ public abstract class ConfPaths {
public static final String PROTECT_PLUGINS_HIDE_NOPERMISSION_MSG = PROTECT_PLUGINS_HIDE_NOPERMISSION + "message"; public static final String PROTECT_PLUGINS_HIDE_NOPERMISSION_MSG = PROTECT_PLUGINS_HIDE_NOPERMISSION + "message";
public static final String PROTECT_PLUGINS_HIDE_NOPERMISSION_CMDS = PROTECT_PLUGINS_HIDE_NOPERMISSION + "commands"; public static final String PROTECT_PLUGINS_HIDE_NOPERMISSION_CMDS = PROTECT_PLUGINS_HIDE_NOPERMISSION + "commands";
// Checks!
private static final String CHECKS = "checks."; private static final String CHECKS = "checks.";
/** Debug flag to debug all checks (!), individual sections debug flags override this, if present. */ /** Debug flag to debug all checks (!), individual sections debug flags override this, if present. */
public static final String CHECKS_DEBUG = CHECKS + SUB_DEBUG; public static final String CHECKS_DEBUG = CHECKS + SUB_DEBUG;
@ -669,4 +675,6 @@ public abstract class ConfPaths {
public static final String PROTECT_PLUGINS_HIDE_MSG_NOCOMMAND = "protection.plugins.hide.messages.unknowncommand"; public static final String PROTECT_PLUGINS_HIDE_MSG_NOCOMMAND = "protection.plugins.hide.messages.unknowncommand";
@Moved(newPath = PROTECT_PLUGINS_HIDE_NOPERMISSION_MSG) @Moved(newPath = PROTECT_PLUGINS_HIDE_NOPERMISSION_MSG)
public static final String PROTECT_PLUGINS_HIDE_MSG_NOPERMISSION = "protection.plugins.hide.messages.nopermission"; public static final String PROTECT_PLUGINS_HIDE_MSG_NOPERMISSION = "protection.plugins.hide.messages.nopermission";
@Moved(newPath = PROTECT_COMMANDS_CONSOLEONLY_ACTIVE)
public static final String MISCELLANEOUS_OPINCONSOLEONLY = "miscellaneous.opinconsoleonly";
} }

View File

@ -72,7 +72,6 @@ public class DefaultConfig extends ConfigFile {
* d8b Y8b Y8b 888 Y88D Y888 , 888 , 888 888 ,ee 888 888 888 888 , Y888 888P Y888 888P Y88D * d8b Y8b Y8b 888 Y88D Y888 , 888 , 888 888 ,ee 888 888 888 888 , Y888 888P Y888 888P Y88D
* d888b Y8b Y8b 888 d,dP "88,e8' "YeeP" 888 888 "88 888 888 888 "YeeP" "88 88" "88 88" d,dP * d888b Y8b Y8b 888 d,dP "88,e8' "YeeP" 888 888 "88 888 888 888 "YeeP" "88 88" "88 88" d,dP
*/ */
set(ConfPaths.MISCELLANEOUS_OPINCONSOLEONLY, false);
set(ConfPaths.MISCELLANEOUS_MANAGELISTENERS, false); set(ConfPaths.MISCELLANEOUS_MANAGELISTENERS, false);
// set(ConfPaths.MISCELLANEOUS_CHECKFORUPDATES, true); // set(ConfPaths.MISCELLANEOUS_CHECKFORUPDATES, true);
set(ConfPaths.MISCELLANEOUS_REPORTTOMETRICS, true); set(ConfPaths.MISCELLANEOUS_REPORTTOMETRICS, true);
@ -98,6 +97,9 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.PROTECT_PLUGINS_HIDE_NOPERMISSION_CMDS, Arrays.asList("plugins", "version", "icanhasbukkit")); set(ConfPaths.PROTECT_PLUGINS_HIDE_NOPERMISSION_CMDS, Arrays.asList("plugins", "version", "icanhasbukkit"));
set(ConfPaths.PROTECT_PLUGINS_HIDE_NOCOMMAND_MSG, "Unknown command. Type \"/help\" for help."); set(ConfPaths.PROTECT_PLUGINS_HIDE_NOCOMMAND_MSG, "Unknown command. Type \"/help\" for help.");
set(ConfPaths.PROTECT_PLUGINS_HIDE_NOCOMMAND_CMDS, new LinkedList<String>()); set(ConfPaths.PROTECT_PLUGINS_HIDE_NOCOMMAND_CMDS, new LinkedList<String>());
// Commands (other).
set(ConfPaths.PROTECT_COMMANDS_CONSOLEONLY_ACTIVE, false);
set(ConfPaths.PROTECT_COMMANDS_CONSOLEONLY_CMDS, Arrays.asList("op", "deop"));
// Client motd. // Client motd.
set(ConfPaths.PROTECT_CLIENTS_MOTD_ACTIVE, true); set(ConfPaths.PROTECT_CLIENTS_MOTD_ACTIVE, true);
set(ConfPaths.PROTECT_CLIENTS_MOTD_ALLOWALL, false); set(ConfPaths.PROTECT_CLIENTS_MOTD_ALLOWALL, false);
@ -202,7 +204,7 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.CHAT_COMMANDS_CHECK, true); set(ConfPaths.CHAT_COMMANDS_CHECK, true);
set(ConfPaths.CHAT_COMMANDS_EXCLUSIONS, new ArrayList<String>()); set(ConfPaths.CHAT_COMMANDS_EXCLUSIONS, new ArrayList<String>());
set(ConfPaths.CHAT_COMMANDS_HANDLEASCHAT, Arrays.asList("/me")); set(ConfPaths.CHAT_COMMANDS_HANDLEASCHAT, Arrays.asList("me"));
set(ConfPaths.CHAT_COMMANDS_LEVEL, 10); set(ConfPaths.CHAT_COMMANDS_LEVEL, 10);
set(ConfPaths.CHAT_COMMANDS_SHORTTERM_TICKS, 18); set(ConfPaths.CHAT_COMMANDS_SHORTTERM_TICKS, 18);
set(ConfPaths.CHAT_COMMANDS_SHORTTERM_LEVEL, 3); set(ConfPaths.CHAT_COMMANDS_SHORTTERM_LEVEL, 3);