diff --git a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java index 5535911..885bb90 100755 --- a/src/main/java/de/diddiz/LogBlock/CommandsHandler.java +++ b/src/main/java/de/diddiz/LogBlock/CommandsHandler.java @@ -17,8 +17,12 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitScheduler; +import java.io.BufferedOutputStream; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileOutputStream; import java.io.FileWriter; +import java.io.OutputStreamWriter; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -295,9 +299,10 @@ public class CommandsHandler implements CommandExecutor { } } else if (command.equals("clearlog")) { if (logblock.hasPermission(sender, "logblock.clearlog")) { - final QueryParams params = new QueryParams(logblock, sender, argsToList(args, 1)); - params.bct = BlockChangeType.ALL; + final QueryParams params = new QueryParams(logblock); params.limit = -1; + params.bct = BlockChangeType.ALL; + params.parseArgs(sender, argsToList(args, 1)); new CommandClearLog(sender, params, true); } else { sender.sendMessage(ChatColor.RED + "You aren't allowed to do this"); @@ -533,7 +538,11 @@ public class CommandsHandler implements CommandExecutor { return; } state = conn.createStatement(); - file = new File("plugins/LogBlock/log/" + params.getTitle().replace(":", ".").replace("/", "_") + ".log"); + final File dumpFolder = new File(logblock.getDataFolder(), "log"); + if (!dumpFolder.exists()) { + dumpFolder.mkdirs(); + } + file = new File(dumpFolder, params.getTitle().replace(":", ".").replace("/", "_").replace("\\", "_") + ".log"); sender.sendMessage(ChatColor.GREEN + "Creating " + file.getName()); rs = executeQuery(state, params.getQuery()); file.getParentFile().mkdirs(); @@ -798,6 +807,7 @@ public class CommandsHandler implements CommandExecutor { public void run() { try { conn = logblock.getConnection(); + conn.setAutoCommit(true); state = conn.createStatement(); if (conn == null) { sender.sendMessage(ChatColor.RED + "MySQL connection lost"); @@ -806,55 +816,131 @@ public class CommandsHandler implements CommandExecutor { if (!checkRestrictions(sender, params)) { return; } + if (params.sum != SummarizationMode.NONE) { + sender.sendMessage(ChatColor.RED + "Cannot summarize on ClearLog"); + return; + } + String tableBase; + String deleteFromTables; + String tableName; + params.needId = true; + params.needDate = true; + params.needPlayer = false; + params.needPlayerId = true; + if (params.bct == BlockChangeType.CHAT) { + params.needMessage = true; + tableBase = "lb-chat"; + deleteFromTables = "`lb-chat` "; + tableName = "lb-chat"; + } else if (params.bct == BlockChangeType.KILLS) { + params.needWeapon = true; + params.needCoords = true; + tableBase = params.getTable(); + deleteFromTables = "`" + tableBase + "-kills` "; + tableName = tableBase + "-kills"; + } else { + params.needType = true; + params.needCoords = true; + params.needData = true; + params.needChestAccess = true; + tableBase = params.getTable(); + deleteFromTables = "`" + tableBase + "-blocks`, `" + tableBase + "-state`, `" + tableBase + "-chestdata` "; + tableName = tableBase + "-blocks"; + } final File dumpFolder = new File(logblock.getDataFolder(), "dump"); if (!dumpFolder.exists()) { dumpFolder.mkdirs(); } - final String time = new SimpleDateFormat("yyMMddHHmmss").format(System.currentTimeMillis()); - int deleted; - final String table = params.getTable(); - final String join = params.players.size() > 0 ? "INNER JOIN `lb-players` USING (playerid) " : ""; - rs = state.executeQuery("SELECT count(*) FROM `" + table + "-blocks` " + join + params.getWhere()); - rs.next(); - if ((deleted = rs.getInt(1)) > 0) { - if (!params.silent && askClearLogs && sender instanceof Player) { - sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); - sender.sendMessage(ChatColor.GREEN.toString() + deleted + " blocks found."); - if (!logblock.getQuestioner().ask((Player) sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { - sender.sendMessage(ChatColor.RED + "ClearLog aborted"); - return; - } + rs = state.executeQuery("SELECT count(*) " + params.getFrom() + params.getWhere()); + int deleted = rs.next() ? rs.getInt(1) : 0; + rs.close(); + if (deleted == 0) { + if (!params.silent) { + sender.sendMessage(ChatColor.GREEN.toString() + deleted + " entries found."); } - if (dumpDeletedLog) { + return; + } + if (!params.silent && askClearLogs && sender instanceof Player) { + sender.sendMessage(ChatColor.DARK_AQUA + "Searching " + params.getTitle() + ":"); + sender.sendMessage(ChatColor.GREEN.toString() + deleted + " entries found."); + if (!logblock.getQuestioner().ask((Player) sender, "Are you sure you want to continue?", "yes", "no").equals("yes")) { + sender.sendMessage(ChatColor.RED + "ClearLog aborted"); + return; + } + } + if (dumpDeletedLog) { + final String time = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(System.currentTimeMillis()); + try { + File outFile = new File(dumpFolder, (time + " " + tableName + " " + params.getTitle() + ".sql").replace(':', '.').replace('/', '_').replace('\\', '_')); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(outFile)), "UTF-8")); try { - state.execute("SELECT * FROM `" + table + "-blocks` " + join + params.getWhere() + "INTO OUTFILE '" + new File(dumpFolder, time + " " + table + " " + params.getTitle().replace(":", ".") + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); - } catch (final SQLException ex) { - sender.sendMessage(ChatColor.RED + "Error while dumping log. Make sure your MySQL user has access to the LogBlock folder, or disable clearlog.dumpDeletedLog"); - logblock.getLogger().log(Level.SEVERE, "[ClearLog] Exception while dumping log: ", ex); - return; + rs = state.executeQuery("SELECT " + params.getFields() + params.getFrom() + params.getWhere()); + while (rs.next()) { + StringBuilder sb = new StringBuilder(); + if (params.bct == BlockChangeType.CHAT) { + sb.append("INSERT INTO `lb-chat` (`id`, `date`, `playerid`, `message`) VALUES ("); + sb.append(rs.getInt("id")).append(", FROM_UNIXTIME("); + sb.append(rs.getTimestamp("date").getTime() / 1000).append("), "); + sb.append(rs.getInt("playerid")).append(", '"); + sb.append(Utils.mysqlTextEscape(rs.getString("message"))); + sb.append("');\n"); + } else if (params.bct == BlockChangeType.KILLS) { + sb.append("INSERT INTO `").append(tableBase).append("-kills` (`id`, `date`, `killer`, `victim`, `weapon`, `x`, `y`, `z`) VALUES ("); + sb.append(rs.getInt("id")).append(", FROM_UNIXTIME("); + sb.append(rs.getTimestamp("date").getTime() / 1000).append("), "); + sb.append(rs.getInt("killerid")).append(", "); + sb.append(rs.getInt("victimid")).append(", "); + sb.append(rs.getInt("weapon")).append(", "); + sb.append(rs.getInt("x")).append(", "); + sb.append(rs.getInt("y")).append(", "); + sb.append(rs.getInt("z")); + sb.append(");\n"); + } else { + sb.append("INSERT INTO `").append(tableBase).append("-blocks` (`id`, `date`, `playerid`, `replaced`, `replacedData`, `type`, `typeData`, `x`, `y`, `z`) VALUES ("); + sb.append(rs.getInt("id")).append(", FROM_UNIXTIME("); + sb.append(rs.getTimestamp("date").getTime() / 1000).append("), "); + sb.append(rs.getInt("playerid")).append(", "); + sb.append(rs.getInt("replaced")).append(", "); + sb.append(rs.getInt("replacedData")).append(", "); + sb.append(rs.getInt("type")).append(", "); + sb.append(rs.getInt("typeData")).append(", "); + sb.append(rs.getInt("x")).append(", "); + sb.append(rs.getInt("y")).append(", "); + sb.append(rs.getInt("z")); + sb.append(");\n"); + byte[] replacedState = rs.getBytes("replacedState"); + byte[] typeState = rs.getBytes("typeState"); + if (replacedState != null || typeState != null) { + sb.append("INSERT INTO `").append(tableBase).append("-state` (`id`, `replacedState`, `typeState`) VALUES ("); + sb.append(rs.getInt("id")).append(", "); + sb.append(Utils.mysqlPrepareBytesForInsertAllowNull(replacedState)).append(", "); + sb.append(Utils.mysqlPrepareBytesForInsertAllowNull(typeState)); + sb.append(");\n"); + } + byte[] item = rs.getBytes("item"); + if (item != null) { + sb.append("INSERT INTO `").append(tableBase).append("-chestdata` (`id`, `item`, `itemremove`, `itemtype`) VALUES ("); + sb.append(rs.getInt("id")).append(", "); + sb.append(Utils.mysqlPrepareBytesForInsertAllowNull(item)).append(", "); + sb.append(rs.getInt("itemremove")).append(", "); + sb.append(rs.getInt("itemtype")); + sb.append(");\n"); + } + } + writer.write(sb.toString()); + } + rs.close(); + } finally { + writer.close(); } + } catch (final SQLException ex) { + sender.sendMessage(ChatColor.RED + "Error while dumping log."); + logblock.getLogger().log(Level.SEVERE, "[ClearLog] Exception while dumping log: ", ex); + return; } - state.execute("DELETE `" + table + "-blocks` FROM `" + table + "-blocks` " + join + params.getWhere()); - sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + ". Deleted " + deleted + " entries."); - } - rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-state` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL"); - rs.next(); - if ((deleted = rs.getInt(1)) > 0) { - if (dumpDeletedLog) { - state.execute("SELECT id, replacedState, typeState FROM `" + table + "-state` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL INTO OUTFILE '" + new File(dumpFolder, time + " " + table + "-state " + params.getTitle() + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); - } - state.execute("DELETE `" + table + "-state` FROM `" + table + "-state` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL;"); - sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-state. Deleted " + deleted + " entries."); - } - rs = state.executeQuery("SELECT COUNT(*) FROM `" + table + "-chestdata` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL"); - rs.next(); - if ((deleted = rs.getInt(1)) > 0) { - if (dumpDeletedLog) { - state.execute("SELECT id, item, itemremove, itemtype FROM `" + table + "-chestdata` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL INTO OUTFILE '" + new File(dumpFolder, time + " " + table + "-chest " + params.getTitle() + ".csv").getAbsolutePath().replace("\\", "\\\\") + "' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n'"); - } - state.execute("DELETE `" + table + "-chestdata` FROM `" + table + "-chestdata` LEFT JOIN `" + table + "-blocks` USING (id) WHERE `" + table + "-blocks`.id IS NULL;"); - sender.sendMessage(ChatColor.GREEN + "Cleared out table " + table + "-chestdata. Deleted " + deleted + " entries."); } + state.executeUpdate("DELETE " + deleteFromTables + params.getFrom() + params.getWhere()); + sender.sendMessage(ChatColor.GREEN + "Cleared out table " + tableName + ". Deleted " + deleted + " entries."); } catch (final Exception ex) { if (logblock.isCompletelyEnabled() || !(ex instanceof SQLException)) { sender.sendMessage(ChatColor.RED + "Exception, check error log"); diff --git a/src/main/java/de/diddiz/LogBlock/QueryParams.java b/src/main/java/de/diddiz/LogBlock/QueryParams.java index 04972c7..0fd9a54 100644 --- a/src/main/java/de/diddiz/LogBlock/QueryParams.java +++ b/src/main/java/de/diddiz/LogBlock/QueryParams.java @@ -65,7 +65,7 @@ public final class QueryParams implements Cloneable { public List typeIds = new ArrayList(); public World world = null; public String match = null; - public boolean needCount = false, needId = false, needDate = false, needType = false, needData = false, needPlayer = false, needCoords = false, needChestAccess = false, needMessage = false, needKiller = false, needVictim = false, needWeapon = false; + public boolean needCount = false, needId = false, needDate = false, needType = false, needData = false, needPlayerId = false, needPlayer = false, needCoords = false, needChestAccess = false, needMessage = false, needKiller = false, needVictim = false, needWeapon = false; private final LogBlock logblock; public QueryParams(LogBlock logblock) { @@ -160,7 +160,10 @@ public final class QueryParams implements Cloneable { select += "date, "; } if (needPlayer) { - select += "playername, UUID,"; + select += "playername, UUID, "; + } + if (needPlayerId) { + select += "playerid, "; } if (needMessage) { select += "message, "; @@ -186,6 +189,9 @@ public final class QueryParams implements Cloneable { if (needPlayer || needVictim) { select += "victims.playername as victim, "; } + if (needPlayerId) { + select += "killer as killerid, victim as victimid, "; + } if (needWeapon) { select += "weapon, "; } @@ -201,7 +207,7 @@ public final class QueryParams implements Cloneable { select += "COUNT(*) AS count "; } else { if (needId) { - select += "`" + getTable() + "`-blocks.id, "; + select += "`" + getTable() + "-blocks`.id, "; } if (needDate) { select += "date, "; @@ -215,6 +221,9 @@ public final class QueryParams implements Cloneable { if (needPlayer) { select += "playername, UUID, "; } + if (needPlayerId) { + select += "playerid, "; + } if (needCoords) { select += "x, y, z, "; } @@ -305,7 +314,7 @@ public final class QueryParams implements Cloneable { } else if (since > 0) { title.append("in the last ").append(since).append(" minutes "); } else if (before > 0) { - title.append("more than ").append(before * -1).append(" minutes ago "); + title.append("more than ").append(before).append(" minutes ago "); } if (loc != null) { if (radius > 0) {