From df70fbac10956c28b363f42b094d4434c55635ff Mon Sep 17 00:00:00 2001 From: Nick Perkins Date: Tue, 29 Oct 2013 00:30:04 +1000 Subject: [PATCH 1/4] Create IPBan class. Adjust super classes to accept IP as subject. --- .../informaban/events/Event.java | 8 +- .../informaban/events/IPBan.java | 183 ++++++++++++++++++ .../informaban/events/TimedEvent.java | 8 + 3 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/lethargiclion/informaban/events/IPBan.java diff --git a/src/main/java/net/lethargiclion/informaban/events/Event.java b/src/main/java/net/lethargiclion/informaban/events/Event.java index 924c2f0..47876c3 100644 --- a/src/main/java/net/lethargiclion/informaban/events/Event.java +++ b/src/main/java/net/lethargiclion/informaban/events/Event.java @@ -18,6 +18,8 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import com.google.common.net.InetAddresses; + /** * This base class represents a record of a ban, kick, jailing or other event * tracked by InformaBan. @@ -167,13 +169,17 @@ protected boolean apply(Player subject, CommandSender enforcer, } /** - * Applies this event to an offline subject. No IP is recorded. + * Applies this event to an offline subject. Accepts IP or player as subject. */ protected boolean apply(String subject, CommandSender enforcer, String reason) { if (getDateIssued() != null) return false; setDateIssued(new Date()); + if (InetAddresses.isInetAddress(subject)) { + this.subjectIP = subject; + + } this.subject = subject; this.enforcer = enforcer.getName(); this.reason = reason; diff --git a/src/main/java/net/lethargiclion/informaban/events/IPBan.java b/src/main/java/net/lethargiclion/informaban/events/IPBan.java new file mode 100644 index 0000000..b97922c --- /dev/null +++ b/src/main/java/net/lethargiclion/informaban/events/IPBan.java @@ -0,0 +1,183 @@ +package net.lethargiclion.informaban.events; + +import java.net.InetAddress; +import java.text.DateFormat; +import java.util.ResourceBundle; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import com.google.common.net.InetAddresses; + +@Entity() +@DiscriminatorValue("IPBAN") +public class IPBan extends TimedEvent { + + public IPBan() { + } + + /** + * Enforce this ban. + * + * Note that this performs the initial enforcement of the ban, e.g. when the + * ban was initially placed. + * + * @param subject + * The player being banned. + * @param enforcer + * The player (or console) performing the ban. + * @param reason + * The reason given for the ban. + * @param duration + * The length of the ban in seconds, or 0 for a permanent ban. + * @return true if successfully enforced; false if the ban has already been + * enforced. + */ + public boolean apply(ResourceBundle messages, Player subject, + CommandSender enforcer, String reason, int duration) { + if (this.getDateIssued() != null) + return false; + + super.apply(subject, enforcer, reason, duration); + + // ResourceBundle messages = ResourceBundle.getBundle("Messages", + // InformaBan.getLocale()); + + String[] message = new String[3]; + + String serverName = "this server"; + + message[0] = String.format("%s%s has %sbanned you from %s!", + ChatColor.GOLD, enforcer.getName(), + isPermanent() ? "PERMANENTLY " : "", serverName); + message[1] = String.format("Reason: %s%s%s", ChatColor.GRAY, + ChatColor.ITALIC, reason); + message[2] = String.format( + "%sYour ban will %s.", + ChatColor.GRAY, + isPermanent() ? "NOT expire" : (String.format( + "expire in %d seconds", duration))); + + subject.setBanned(true); + subject.kickPlayer(StringUtils.join(message, '\n')); + return true; + } + + /** + * Enforce this ban. + * + * Note that this performs the initial enforcement of the ban, e.g. when the + * ban was initially placed. + * + * @param subject + * The IP being banned. + * @param enforcer + * The player (or console) performing the ban. + * @param reason + * The reason given for the ban. + * @param duration + * The length of the ban in seconds, or 0 for a permanent ban. + * @return true if successfully enforced; false if the ban has already been + * enforced. + */ + public boolean apply(ResourceBundle messages, String subject, + CommandSender enforcer, String reason, int duration) { + if (this.getDateIssued() != null) + return false; + + super.apply(subject, enforcer, reason, duration); + + // ResourceBundle messages = ResourceBundle.getBundle("Messages", + // InformaBan.getLocale()); + + String[] message = new String[3]; + + String serverName = "this server"; + + message[0] = String.format("%s%s has %sbanned you from %s!", + ChatColor.GOLD, enforcer.getName(), + isPermanent() ? "PERMANENTLY " : "", serverName); + message[1] = String.format("Reason: %s%s%s", ChatColor.GRAY, + ChatColor.ITALIC, reason); + message[2] = String.format( + "%sYour ban will %s.", + ChatColor.GRAY, + isPermanent() ? "NOT expire" : (String.format( + "expire in %d seconds", duration))); + + Player[] players = Bukkit.getOnlinePlayers(); + for (Player p: players) { + if (p.getAddress().getHostString().equals(subject)) { + p.setBanned(true); + p.kickPlayer(StringUtils.join(message, '\n')); + } + } + return true; + } + + /** + * Fetches the string that should be used as the kick message if the subject + * of this ban attempts to log in. + * + * @return + */ + public String getMessage() { + String[] message = new String[3]; + String serverName = "this server"; + + message[0] = String + .format("%sYou are %sbanned from %s!", ChatColor.GOLD, + isPermanent() ? "PERMANENTLY " : "", serverName); + message[1] = String.format("Reason: %s%s%s", ChatColor.GRAY, + ChatColor.ITALIC, getReason()); + message[2] = String.format( + "%sYour ban (placed by %s%s%s) will %s.", + ChatColor.GRAY, + ChatColor.WHITE, + this.getEnforcer(), + ChatColor.GRAY, + getDuration() != 0 ? String.format("expire in %d seconds", + getDuration()) : "NOT expire"); + + return StringUtils.join(message, '\n'); + + } + + @Override + public String toString() { + if(isPermanent()) return String.format("%s: %s permanently banned %s: %s", + DateFormat.getInstance().format(getDateIssued()), + getEnforcer(), getSubject(), + getReason()); + + else return String.format("%s: %s banned %s for %d seconds: %s", + DateFormat.getInstance().format(getDateIssued()), + getEnforcer(), getSubject(), + getDuration(), getReason()); + } + + @Override + /** + * Process actions to be taken when the user's ban has expired. + * Nothing to do here for a ban. + */ + public void onExpire() { + + } + + @Override + public ActiveEvent makeActiveEvent() { + ActiveEvent ab = new ActiveBan(); + ab.setParent(this); + ab.setSubject(getSubject()); + ab.setExpiry(getExpiryDate()); + return ab; + } + +} diff --git a/src/main/java/net/lethargiclion/informaban/events/TimedEvent.java b/src/main/java/net/lethargiclion/informaban/events/TimedEvent.java index 9129edc..2c8ee5e 100644 --- a/src/main/java/net/lethargiclion/informaban/events/TimedEvent.java +++ b/src/main/java/net/lethargiclion/informaban/events/TimedEvent.java @@ -31,6 +31,14 @@ protected boolean apply(Player subject, CommandSender issuer, setDuration(duration); return true; } + + protected boolean apply(String subject, CommandSender issuer, + String reason, int duration) { + if (!super.apply(subject, issuer, reason)) { + return false; + } + return true; + } /** * Reverses the actions (if any) taken when apply() was called on the From e4c74eb66d093bb79bcd3492f1f9417a38c71583 Mon Sep 17 00:00:00 2001 From: Nick Perkins Date: Tue, 29 Oct 2013 18:06:33 +1000 Subject: [PATCH 2/4] Add CommandExecutor and Update Event Listener for IP Ban --- .../lethargiclion/informaban/InformaBan.java | 9 ++ .../informaban/InformaBanCommandExecutor.java | 82 +++++++++++++++++-- .../informaban/InformaBanEventListener.java | 1 + .../informaban/events/IPBan.java | 5 +- src/main/resources/Messages.properties | 1 + src/main/resources/plugin.yml | 5 ++ 6 files changed, 93 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/lethargiclion/informaban/InformaBan.java b/src/main/java/net/lethargiclion/informaban/InformaBan.java index d88ad71..bf6db72 100644 --- a/src/main/java/net/lethargiclion/informaban/InformaBan.java +++ b/src/main/java/net/lethargiclion/informaban/InformaBan.java @@ -72,6 +72,7 @@ private void createDBClassList() { ebeans.add(net.lethargiclion.informaban.events.Event.class); ebeans.add(net.lethargiclion.informaban.events.TimedEvent.class); ebeans.add(net.lethargiclion.informaban.events.Ban.class); + ebeans.add(net.lethargiclion.informaban.events.IPBan.class); ebeans.add(net.lethargiclion.informaban.events.Unban.class); ebeans.add(net.lethargiclion.informaban.events.Kick.class); ebeans.add(net.lethargiclion.informaban.events.ActiveEvent.class); @@ -143,6 +144,14 @@ public void onEnable() { } else log.warning(msgFailed.format(new Object[] { "/ban" })); + PluginCommand ipban = getCommand("ipban"); + if (ipban != null) { + ipban.setExecutor(commandExecutor); + ipban.setDescription(messages.getString("command.ban.description")); + ipban.setUsage(messages.getString("command.ban.usage")); + } else + log.warning(msgFailed.format(new Object[] { "/ban" })); + PluginCommand unban = getCommand("unban"); if (unban != null) { unban.setExecutor(commandExecutor); diff --git a/src/main/java/net/lethargiclion/informaban/InformaBanCommandExecutor.java b/src/main/java/net/lethargiclion/informaban/InformaBanCommandExecutor.java index 7a13f60..e79fb3d 100644 --- a/src/main/java/net/lethargiclion/informaban/InformaBanCommandExecutor.java +++ b/src/main/java/net/lethargiclion/informaban/InformaBanCommandExecutor.java @@ -25,6 +25,7 @@ import net.lethargiclion.informaban.events.ActiveBan; import net.lethargiclion.informaban.events.Ban; import net.lethargiclion.informaban.events.Event; +import net.lethargiclion.informaban.events.IPBan; import net.lethargiclion.informaban.events.Kick; import net.lethargiclion.informaban.events.Unban; @@ -34,6 +35,8 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import com.google.common.net.InetAddresses; + /** * InformaBan command executor class. Processes commands. * @@ -66,6 +69,8 @@ public boolean onCommand(CommandSender sender, Command command, return commandRap(sender, args); if (command.getName().equalsIgnoreCase("ban")) return commandBan(sender, args); + if (command.getName().equalsIgnoreCase("ipban")) + return commandIPBan(sender, args); if (command.getName().equalsIgnoreCase("unban")) return commandUnban(sender, args); } catch (java.util.MissingResourceException e) { @@ -103,8 +108,8 @@ private boolean commandKick(CommandSender sender, String[] args) { MessageFormat.format( plugin.messages .getString("command.kick.consoleLog"), - new Object[] { sender.getName(), - victim.getName() })); + new Object[] {sender.getName(), + victim.getName()})); // Do the kick and record it Kick k = new Kick(); @@ -137,14 +142,14 @@ private boolean commandBan(CommandSender sender, String[] args) { // Set up ban message String banReason = StringUtils.join( Arrays.copyOfRange(args, 1, args.length), ' '); - + // Log ban to console plugin.getLogger().info( MessageFormat.format( plugin.messages .getString("command.ban.consoleLog"), - new Object[] { sender.getName(), - victim.getName() })); + new Object[] {sender.getName(), + victim.getName()})); // Do the ban and record it Ban b = new Ban(); @@ -160,6 +165,69 @@ private boolean commandBan(CommandSender sender, String[] args) { return false; } + /** + * Handles the /ipban command. + * + * @param sender + * The CommandSender executing this command. + * @param args + * The command arguments. + * @return False if a usage message should be displayed. + */ + private boolean commandIPBan(CommandSender sender, String[] args) { + + + if (args.length == 1) + sender.sendMessage(plugin.messages + .getString("command.ban.reasonRequired")); + + String subject = null; + + if (args.length > 1) { + if (InetAddresses.isInetAddress(args[0])) { + subject = args[0]; + } else { + subject = sender.getServer().getPlayer(args[0]).getAddress().getHostName(); + } + + // Check for existing IP ban + ActiveBan ab = plugin.getDatabase().find(ActiveBan.class).where() + .eq("subject", subject) + .findUnique(); + + if (ab != null) { + sender.sendMessage(plugin.messages + .getString("error.IPAlreadyBanned")); + return true; + } + + if (subject != null) { + // Set up ban message + String banReason = StringUtils.join( + Arrays.copyOfRange(args, 1, args.length), ' '); + + // Log ban to console + plugin.getLogger().info( + MessageFormat.format( + plugin.messages + .getString("command.ban.consoleLog"), + new Object[] {sender.getName(), + subject})); + + // Do the ban and record it + IPBan b = new IPBan(); + b.apply(plugin.messages, subject, sender, banReason, + Ban.PERMANENT); + plugin.getDatabase().insert(b); // Record the banning event + plugin.getDatabase().insert(b.makeActiveEvent()); // Set the actual ban + } else + sender.sendMessage(plugin.messages + .getString("error.playerNotFound")); + return true; + } + return false; + } + /** * Handles the /rap command. * @@ -214,8 +282,8 @@ private boolean commandUnban(CommandSender sender, String[] args) { MessageFormat.format( plugin.messages .getString("command.unban.consoleLog"), - new Object[] { sender.getName(), - ab.getSubject() })); + new Object[] {sender.getName(), + ab.getSubject()})); // Do the unban and record it Unban b = new Unban(); diff --git a/src/main/java/net/lethargiclion/informaban/InformaBanEventListener.java b/src/main/java/net/lethargiclion/informaban/InformaBanEventListener.java index ea00b04..f2e0d31 100644 --- a/src/main/java/net/lethargiclion/informaban/InformaBanEventListener.java +++ b/src/main/java/net/lethargiclion/informaban/InformaBanEventListener.java @@ -79,6 +79,7 @@ private void checkBans(PlayerLoginEvent event) { .eq("subject", event.getAddress().getHostAddress()) .findUnique(); + if (b != null) { if (b.isActive()) { event.setKickMessage(b.getParent().getMessage()); diff --git a/src/main/java/net/lethargiclion/informaban/events/IPBan.java b/src/main/java/net/lethargiclion/informaban/events/IPBan.java index b97922c..ed7f908 100644 --- a/src/main/java/net/lethargiclion/informaban/events/IPBan.java +++ b/src/main/java/net/lethargiclion/informaban/events/IPBan.java @@ -1,6 +1,5 @@ package net.lethargiclion.informaban.events; -import java.net.InetAddress; import java.text.DateFormat; import java.util.ResourceBundle; @@ -13,8 +12,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import com.google.common.net.InetAddresses; - @Entity() @DiscriminatorValue("IPBAN") public class IPBan extends TimedEvent { @@ -111,6 +108,8 @@ public boolean apply(ResourceBundle messages, String subject, isPermanent() ? "NOT expire" : (String.format( "expire in %d seconds", duration))); + Bukkit.banIP(subject); + Player[] players = Bukkit.getOnlinePlayers(); for (Player p: players) { if (p.getAddress().getHostString().equals(subject)) { diff --git a/src/main/resources/Messages.properties b/src/main/resources/Messages.properties index f8533b7..04eeb9e 100644 --- a/src/main/resources/Messages.properties +++ b/src/main/resources/Messages.properties @@ -25,6 +25,7 @@ command.unban.consoleLog = {0} unbanned {1} from the server. command.rap.clean = There is nothing recorded for {0}. error.playerNotFound = Could not find that player. error.playerNotBanned = That player is not currently banned. +error.IPAlreadyBanned = That IP is already banned. banmsg.kickedby = You have been kicked by {0}! banmsg.reason = Reason \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index cda771b..e18aa80 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -19,6 +19,11 @@ commands: usage: /ban