diff --git a/src/com/sk89q/worldguard/blacklist/Blacklist.java b/src/com/sk89q/worldguard/blacklist/Blacklist.java index b37b7275..08526ac5 100644 --- a/src/com/sk89q/worldguard/blacklist/Blacklist.java +++ b/src/com/sk89q/worldguard/blacklist/Blacklist.java @@ -87,6 +87,24 @@ public List getEntries(int id) { return blacklist.get(id); } + /** + * Get the number of individual items that have blacklist entries. + * + * @return + */ + public int getItemCount() { + return blacklist.size(); + } + + /** + * Returns whether the blacklist is used as a whitelist. + * + * @return + */ + public boolean isWhitelist() { + return useAsWhitelist; + } + /** * Get the logger. * diff --git a/src/com/sk89q/worldguard/bukkit/ReportWriter.java b/src/com/sk89q/worldguard/bukkit/ReportWriter.java new file mode 100644 index 00000000..2c9f7363 --- /dev/null +++ b/src/com/sk89q/worldguard/bukkit/ReportWriter.java @@ -0,0 +1,287 @@ +// $Id$ +/* + * WorldGuard + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldguard.bukkit; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.*; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.Plugin; +import com.sk89q.worldguard.protection.GlobalRegionManager; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.managers.RegionManager; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; + +public class ReportWriter { + + private static final SimpleDateFormat dateFmt = + new SimpleDateFormat("yyyy-MM-dd kk:mm Z"); + + private WorldGuardPlugin plugin; + private Date date = new Date(); + private StringBuilder output = new StringBuilder(); + + public ReportWriter(WorldGuardPlugin plugin) { + this.plugin = plugin; + + appendHeader(plugin); + appendServerInformation(plugin.getServer()); + appendPluginInformation(plugin.getServer().getPluginManager().getPlugins()); + appendWorldInformation(plugin.getServer().getWorlds()); + appendGlobalConfiguration(plugin.getGlobalConfiguration()); + appendWorldConfigurations(plugin, plugin.getServer().getWorlds(), + plugin.getGlobalRegionManager(), plugin.getGlobalConfiguration()); + appendRule(); + appendln("END OF REPORT"); + appendln(); + } + + private void appendln(String text) { + output.append(text); + output.append("\r\n"); + } + + private void appendln(String text, Object ... args) { + output.append(String.format(text, args)); + output.append("\r\n"); + } + + private void appendln() { + output.append("\r\n"); + } + + private void appendRule() { + output.append("--------------------------------------------------\r\n"); + } + + private void appendHeader(WorldGuardPlugin plugin) { + appendln("WorldGuard Configuration Report"); + appendln("Generated " + dateFmt.format(date)); + appendln(); + appendln("Version: " + plugin.getDescription().getVersion()); + appendln(); + } + + private void appendGlobalConfiguration(ConfigurationManager config) { + appendRule(); + appendln("GLOBAL CONFIGURATION:"); + appendRule(); + appendln(); + + Class cls = config.getClass(); + for (Field field : cls.getFields()) { + try { + Object val = field.get(config); + appendln("%-30s: %s", field.getName(), String.valueOf(val)); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + } + } + + appendln(); + } + + private void appendServerInformation(Server server) { + appendRule(); + appendln("SERVER:"); + appendRule(); + appendln(); + + appendln("%-15s: %s", "Server ID", server.getServerId()); + appendln("%-15s: %s", "Server name", server.getServerName()); + appendln("%-15s: %s", "Implementation", server.getVersion()); + //appendln("%-15s: %s:%d", "Address", server.getIp(), server.getPort()); + appendln("%-15s: %d/%d", "Player count", + server.getOnlinePlayers().length, server.getMaxPlayers()); + + appendln(); + } + + private void appendPluginInformation(Plugin[] plugins) { + appendRule(); + appendln("PLUGINS (%d)", plugins.length); + appendRule(); + appendln(); + + for (Plugin plugin : plugins) { + appendln("%s %s <%s>:", plugin.getDescription().getName(), + plugin.getDescription().getVersion(), + plugin.getDescription().getWebsite()); + appendln(" %-15s: %s", "Entry point", plugin.getDescription().getMain()); + appendln(" %-15s: %s", "Data folder", plugin.getDataFolder().getAbsoluteFile()); + } + + appendln(); + } + + private void appendWorldInformation(List worlds) { + appendRule(); + appendln("WORLDS (%d)", worlds.size()); + appendRule(); + appendln(); + + int i = 0; + for (World world : worlds) { + int loadedChunkCount = world.getLoadedChunks().length; + + appendln("%d. %s:", i, world.getName()); + appendln(" Information:"); + appendln(" %-15s: %s", "ID", world.getId()); + appendln(" %-15s: %s", "Environment", world.getEnvironment().toString()); + appendln(" %-15s: %d", "Player #", world.getPlayers().size()); + appendln(" %-15s: %d", "Entity #", world.getEntities().size()); + appendln(" %-15s: %d", "Loaded chunk #", loadedChunkCount); + appendln(" Entities:"); + + Map, Integer> entityCounts = + new HashMap, Integer>(); + + // Collect entities + for (Entity entity : world.getEntities()) { + Class cls = entity.getClass(); + + if (entityCounts.containsKey(cls)) { + entityCounts.put(cls, entityCounts.get(cls) + 1); + } else { + entityCounts.put(cls, 1); + } + } + + // Print entities + for (Map.Entry, Integer> entry + : entityCounts.entrySet()) { + appendln(" %-25s: %d [%f]", entry.getKey().getSimpleName(), + entry.getValue(), (float) (entry.getValue() / (double) loadedChunkCount)); + } + + i++; + } + + appendln(); + } + + private void appendWorldConfigurations(WorldGuardPlugin plugin, List worlds, + GlobalRegionManager regionMgr, ConfigurationManager mgr) { + appendRule(); + appendln("WORLD CONFIGURATIONS"); + appendRule(); + appendln(); + + int i = 0; + for (World world : worlds) { + appendln("%d. %s:", i, world.getName()); + + WorldConfiguration config = mgr.get(world); + + appendln(" Configuration:"); + appendln(" %-30s: %s", "File", + (new File(plugin.getDataFolder(), "worlds/" + + world.getName() + "/config.yml")).getAbsoluteFile()); + + Class cls = config.getClass(); + for (Field field : cls.getFields()) { + try { + Object val = field.get(config); + appendln(" %-30s: %s", field.getName(), String.valueOf(val)); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + } + } + + appendln(" Blacklist:"); + appendln(" %-15s: %s", "File", + (new File(plugin.getDataFolder(), "worlds/" + + world.getName() + "/blacklist.txt")).getAbsoluteFile()); + if (config.getBlacklist() == null) { + appendln(" DISABLED / NO ENTRIES"); + } else { + appendln(" %-15s: %s", "Number of items", + config.getBlacklist().getItemCount()); + appendln(" %-15s: %s", "Is whitelist", + config.getBlacklist().isWhitelist() ? "YES" : "NO"); + } + + appendln(" Region manager:"); + appendln(" %-15s: %s", "File", + (new File(plugin.getDataFolder(), "worlds/" + + world.getName() + "/regions.yml")).getAbsoluteFile()); + RegionManager worldRegions = regionMgr.get(world); + appendln(" %-15s: %s", "Type", + worldRegions.getClass().getCanonicalName()); + appendln(" %-15s: %s", "Number of regions", + worldRegions.getRegions().size()); + appendln(" Global region:"); + ProtectedRegion globalRegion = worldRegions.getRegion("__global__"); + if (globalRegion == null) { + appendln(" UNDEFINED"); + } else { + appendln(" %-20s: %s", "Type", + globalRegion.getClass().getCanonicalName()); + for (Flag flag : DefaultFlag.getFlags()) { + if (flag instanceof StateFlag) { + appendln(" %-20s: %s", flag.getName(), + globalRegion.getFlag(flag)); + } + } + } + } + + appendln(); + } + + public void write(File file) throws IOException { + FileWriter writer = null; + BufferedWriter out; + + try { + writer = new FileWriter(file); + out = new BufferedWriter(writer); + out.write(output.toString()); + out.close(); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + } + } + } + } + + @Override + public String toString() { + return output.toString(); + } + +} diff --git a/src/com/sk89q/worldguard/bukkit/commands/WorldGuardCommands.java b/src/com/sk89q/worldguard/bukkit/commands/WorldGuardCommands.java index 823170f6..525ec5b2 100644 --- a/src/com/sk89q/worldguard/bukkit/commands/WorldGuardCommands.java +++ b/src/com/sk89q/worldguard/bukkit/commands/WorldGuardCommands.java @@ -19,6 +19,8 @@ package com.sk89q.worldguard.bukkit.commands; +import java.io.File; +import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import org.bukkit.ChatColor; @@ -29,7 +31,10 @@ import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldguard.bukkit.LoggerToChatHandler; +import com.sk89q.worldguard.bukkit.ReportWriter; import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.util.PastebinPoster; +import com.sk89q.worldguard.util.PastebinPoster.PasteCallback; public class WorldGuardCommands { @@ -77,6 +82,46 @@ public static void relload(CommandContext args, WorldGuardPlugin plugin, minecraftLogger.removeHandler(handler); } } + } + + @Command(aliases = {"report"}, + usage = "", + desc = "Writes a report on WorldGuard", + flags = "p", min = 0, max = 0) + @CommandPermissions({"worldguard.report"}) + public static void report(CommandContext args, WorldGuardPlugin plugin, + final CommandSender sender) throws CommandException { + + File dest = new File(plugin.getDataFolder(), "report.txt"); + ReportWriter report = new ReportWriter(plugin); + + try { + report.write(dest); + sender.sendMessage(ChatColor.YELLOW + "WorldGuard report written to " + + dest.getAbsolutePath()); + } catch (IOException e) { + throw new CommandException("Failed to write report: " + e.getMessage()); + } + + if (args.hasFlag('p')) { + plugin.checkPermission(sender, "worldguard.report.pastebin"); + + sender.sendMessage(ChatColor.YELLOW + "Now uploading to Pastebin..."); + PastebinPoster.paste(report.toString(), new PasteCallback() { + + @Override + public void handleSuccess(String url) { + // Hope we don't have a thread safety issue here + sender.sendMessage(ChatColor.YELLOW + "WorldGuard report (1 hour): " + url); + } + + @Override + public void handleError(String err) { + // Hope we don't have a thread safety issue here + sender.sendMessage(ChatColor.YELLOW + "WorldGuard report pastebin error: " + err); + } + }); + } } } diff --git a/src/com/sk89q/worldguard/util/PastebinPoster.java b/src/com/sk89q/worldguard/util/PastebinPoster.java new file mode 100644 index 00000000..2043be1a --- /dev/null +++ b/src/com/sk89q/worldguard/util/PastebinPoster.java @@ -0,0 +1,132 @@ +// $Id$ +/* + * WorldGuard + * Copyright (C) 2010 sk89q + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +package com.sk89q.worldguard.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; + +public class PastebinPoster { + private static final int CONNECT_TIMEOUT = 5000; + private static final int READ_TIMEOUT = 5000; + + public static void paste(String code, PasteCallback callback) { + PasteProcessor processor = new PasteProcessor(code, callback); + Thread thread = new Thread(processor); + thread.start(); + } + + public static interface PasteCallback { + public void handleSuccess(String url); + public void handleError(String err); + } + + private static class PasteProcessor implements Runnable { + private String code; + private PasteCallback callback; + + public PasteProcessor(String code, PasteCallback callback) { + this.code = code; + this.callback = callback; + } + + @Override + public void run() { + HttpURLConnection conn = null; + OutputStream out = null; + InputStream in = null; + + try { + URL url = new URL("http://pastebin.com/api/api_post.php"); + conn = (HttpURLConnection) url.openConnection(); + conn.setConnectTimeout(CONNECT_TIMEOUT); + conn.setReadTimeout(READ_TIMEOUT); + conn.setRequestMethod("POST"); + conn.addRequestProperty("Content-type", + "application/x-www-form-urlencoded"); + conn.setInstanceFollowRedirects(false); + conn.setDoOutput(true); + out = conn.getOutputStream(); + + out.write(("api_option=paste" + + "&api_dev_key=" + URLEncoder.encode("4867eae74c6990dbdef07c543cf8f805", "utf-8") + + "&api_paste_code=" + URLEncoder.encode(code, "utf-8") + + "&api_paste_private=" + URLEncoder.encode("0", "utf-8") + + "&api_paste_name=" + URLEncoder.encode("", "utf-8") + + "&api_paste_expire_date=" + URLEncoder.encode("1H", "utf-8") + + "&api_paste_format=" + URLEncoder.encode("text", "utf-8") + + "&api_user_key=" + URLEncoder.encode("", "utf-8")).getBytes()); + out.flush(); + out.close(); + + if (conn.getResponseCode() == 200) {//Get Response + in = conn.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String line; + StringBuffer response = new StringBuffer(); + while ((line = reader.readLine()) != null) { + response.append(line); + response.append("\r\n"); + } + reader.close(); + + String result = response.toString().trim(); + + if (result.matches("^https?://.*")) { + callback.handleSuccess(result.trim()); + } else { + String err =result.trim(); + if (err.length() > 100) { + err = err.substring(0, 100); + } + callback.handleError(err); + } + } else { + callback.handleError("didn't get a 200 response code!"); + } + } catch (IOException e) { + callback.handleError(e.getMessage()); + } finally { + if (conn != null) { + conn.disconnect(); + } + if (in != null) { + try { + in.close(); + } catch (IOException e) { + } + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + } + } + } + } + + } + +}