diff --git a/pom.xml b/pom.xml index 84209ab0..e04ee97e 100644 --- a/pom.xml +++ b/pom.xml @@ -24,12 +24,12 @@ - 2.9.3 + 2.9.4 org.bukkit bukkit - 1.6.2-R0.1 + 1.6.2-R1.0 net.milkbowl.vault diff --git a/src/main/java/uk/org/whoami/authme/Management.java b/src/main/java/uk/org/whoami/authme/Management.java index b1df8ba5..ed98ac08 100644 --- a/src/main/java/uk/org/whoami/authme/Management.java +++ b/src/main/java/uk/org/whoami/authme/Management.java @@ -125,11 +125,10 @@ public class Management { } } if (PasswordSecurity.comparePasswordWithHash(password, - hash, name)) { + hash, name) && player.isOnline()) { PlayerAuth auth = new PlayerAuth(name, hash, ip, new Date().getTime(), email); database.updateSession(auth); - PlayerCache.getInstance().addPlayer(auth); final LimboPlayer limbo = LimboCache.getInstance() .getLimboPlayer(name); final PlayerAuth getAuth = database.getAuth(name); @@ -138,8 +137,10 @@ public class Management { new Runnable() { @Override public void run() { - player.setOp(limbo - .getOperator()); + player.setOp(limbo.getOperator()); + if (player.getGameMode() != GameMode.CREATIVE) + player.setAllowFlight(limbo.isFlying()); + player.setFlying(limbo.isFlying()); } }); @@ -244,7 +245,8 @@ public class Management { }); } - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, + if(!Settings.forceOnlyAfterLogin) + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -253,6 +255,14 @@ public class Management { .getGameMode())); } }); + else + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() { + @Override + public void run() { + player.setGameMode(GameMode.SURVIVAL); + } + }); if (Settings.protectInventoryBeforeLogInEnabled && player.hasPlayedBefore()) { @@ -332,6 +342,7 @@ public class Management { plugin.cap.containsKey(name); } } + player.setNoDamageTicks(0); player.sendMessage(m._("login")); displayOtherAccounts(auth); if (!Settings.noConsoleSpam) @@ -343,6 +354,7 @@ public class Management { "[AuthMe] " + player.getName() + " logged in!")); } + PlayerCache.getInstance().addPlayer(auth); Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override @@ -351,7 +363,7 @@ public class Management { } }); - } else { + } else if (player.isOnline()) { if (!Settings.noConsoleSpam) ConsoleLogger.info(player.getName() + " used the wrong password"); @@ -381,6 +393,8 @@ public class Management { player.sendMessage(m._("wrong_pwd")); return; } + } else { + ConsoleLogger.showError("Player " + name + " wasn't online during login process , aborded... "); } } else { // need for bypass password check if passpartu command @@ -388,7 +402,6 @@ public class Management { PlayerAuth auth = new PlayerAuth(name, hash, ip, new Date().getTime(), email); database.updateSession(auth); - PlayerCache.getInstance().addPlayer(auth); final LimboPlayer limbo = LimboCache.getInstance() .getLimboPlayer(name); if (limbo != null) { @@ -398,6 +411,9 @@ public class Management { @Override public void run() { player.setOp(limbo.getOperator()); + if (player.getGameMode() != GameMode.CREATIVE) + player.setAllowFlight(limbo.isFlying()); + player.setFlying(limbo.isFlying()); } }); @@ -546,8 +562,9 @@ public class Management { } }); } - - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, + + if(!Settings.forceOnlyAfterLogin) + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -556,6 +573,14 @@ public class Management { .getGameMode())); } }); + else + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, + new Runnable() { + @Override + public void run() { + player.setGameMode(GameMode.SURVIVAL); + } + }); if (Settings.protectInventoryBeforeLogInEnabled && player.hasPlayedBefore()) { @@ -628,6 +653,7 @@ public class Management { plugin.cap.containsKey(name); } } + player.setNoDamageTicks(0); player.sendMessage(m._("login")); displayOtherAccounts(auth); if (!Settings.noConsoleSpam) @@ -638,6 +664,7 @@ public class Management { "[AuthMe] " + player.getName() + " logged in!")); } + PlayerCache.getInstance().addPlayer(auth); Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { diff --git a/src/main/java/uk/org/whoami/authme/api/API.java b/src/main/java/uk/org/whoami/authme/api/API.java index 976bb37e..851f2c62 100644 --- a/src/main/java/uk/org/whoami/authme/api/API.java +++ b/src/main/java/uk/org/whoami/authme/api/API.java @@ -1,9 +1,6 @@ package uk.org.whoami.authme.api; -import java.lang.reflect.Array; import java.security.NoSuchAlgorithmException; -import java.util.List; - import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -15,9 +12,8 @@ import uk.org.whoami.authme.Utils; import uk.org.whoami.authme.cache.auth.PlayerAuth; import uk.org.whoami.authme.cache.auth.PlayerCache; import uk.org.whoami.authme.datasource.DataSource; -import uk.org.whoami.authme.datasource.DataSource.DataSourceType; +import uk.org.whoami.authme.plugin.manager.CombatTagComunicator; import uk.org.whoami.authme.security.PasswordSecurity; -import uk.org.whoami.authme.security.PasswordSecurity.HashAlgorithm; import uk.org.whoami.authme.settings.Settings; public class API { @@ -59,8 +55,22 @@ public class API { * @param player * @return true if player is a npc */ + @Deprecated public boolean isaNPC(Player player) { - return instance.getCitizensCommunicator().isNPC(player, instance); + if (instance.getCitizensCommunicator().isNPC(player, instance)) + return true; + return CombatTagComunicator.isNPC(player); + } + + /** + * + * @param player + * @return true if player is a npc + */ + public boolean isNPC(Player player) { + if (instance.getCitizensCommunicator().isNPC(player, instance)) + return true; + return CombatTagComunicator.isNPC(player); } /** @@ -95,7 +105,7 @@ public class API { } catch (NullPointerException npe) { } } - + /** * * @param playerName @@ -103,12 +113,9 @@ public class API { */ public static boolean isRegistered(String playerName) { String player = playerName.toLowerCase(); - PlayerAuth auth = database.getAuth(player); - if (auth != null) - return true; - return false; + return database.isAuthAvailable(player); } - + /** * @param String playerName, String passwordToCheck * @return true if the password is correct , false else @@ -123,7 +130,7 @@ public class API { return false; } } - + /** * Register a player * @param String playerName, String password diff --git a/src/main/java/uk/org/whoami/authme/cache/backup/DataFileCache.java b/src/main/java/uk/org/whoami/authme/cache/backup/DataFileCache.java index eaf7b656..e443f1a6 100644 --- a/src/main/java/uk/org/whoami/authme/cache/backup/DataFileCache.java +++ b/src/main/java/uk/org/whoami/authme/cache/backup/DataFileCache.java @@ -16,18 +16,21 @@ public class DataFileCache { private ItemStack[] armor; private String group; private boolean operator; + private boolean flying; public DataFileCache(ItemStack[] inventory, ItemStack[] armor){ this.inventory = inventory; this.armor = armor; } - public DataFileCache(ItemStack[] inventory, ItemStack[] armor, String group, boolean operator){ + public DataFileCache(ItemStack[] inventory, ItemStack[] armor, String group, boolean operator, boolean flying){ this.inventory = inventory; this.armor = armor; this.group = group; this.operator = operator; + this.flying = flying; } + public ItemStack[] getInventory(){ return inventory; } @@ -40,8 +43,11 @@ public class DataFileCache { return group; } - public Boolean getOperator(){ - return operator; + public boolean getOperator(){ + return operator; } + public boolean isFlying(){ + return flying; + } } diff --git a/src/main/java/uk/org/whoami/authme/cache/backup/FileCache.java b/src/main/java/uk/org/whoami/authme/cache/backup/FileCache.java index a5841af8..c4110cfb 100644 --- a/src/main/java/uk/org/whoami/authme/cache/backup/FileCache.java +++ b/src/main/java/uk/org/whoami/authme/cache/backup/FileCache.java @@ -24,7 +24,7 @@ public class FileCache { } } - public void createCache(String playername, DataFileCache playerData, String group, boolean operator) { + public void createCache(String playername, DataFileCache playerData, String group, boolean operator, boolean flying) { final File file = new File("cache/" + playername + ".cache"); @@ -38,10 +38,15 @@ public class FileCache { writer = new FileWriter(file); - // line format Group|OperatorStatus - if(operator) - writer.write(group+";1\r\n"); - else writer.write(group+";0\r\n"); + String s = group+";"; + if (operator) + s = s + "1"; + else s = s + "0"; + + // line format Group|OperatorStatus|isFlying + if(flying) + writer.write(s+";1\r\n"); + else writer.write(s+";0\r\n"); writer.flush(); ItemStack[] invstack = playerData.getInventory(); @@ -98,6 +103,7 @@ public class FileCache { ItemStack[] stacka = new ItemStack[4]; String group = null; boolean op = false; + boolean flying = false; if (!file.exists()) { return new DataFileCache(stacki, stacka); } @@ -112,14 +118,19 @@ public class FileCache { final String line = reader.nextLine(); if (!line.contains(":")) { - // the fist line rapresent the player group and operator status + // the fist line represent the player group, operator status and flying status final String[] playerInfo = line.split(";"); group = playerInfo[0]; - + if (Integer.parseInt(playerInfo[1]) == 1) { op = true; } else op = false; - + if (playerInfo.length > 2) { + if (Integer.parseInt(playerInfo[2]) == 1) + flying = true; + else flying = false; + } + continue; } @@ -157,7 +168,7 @@ public class FileCache { reader.close(); } } - return new DataFileCache(stacki, stacka, group, op); + return new DataFileCache(stacki, stacka, group, op, flying); } public void removeCache(String playername) { diff --git a/src/main/java/uk/org/whoami/authme/cache/limbo/LimboCache.java b/src/main/java/uk/org/whoami/authme/cache/limbo/LimboCache.java index ae8b9a06..ba3153d1 100644 --- a/src/main/java/uk/org/whoami/authme/cache/limbo/LimboCache.java +++ b/src/main/java/uk/org/whoami/authme/cache/limbo/LimboCache.java @@ -50,6 +50,7 @@ public class LimboCache { ItemStack[] inv; boolean operator; String playerGroup = ""; + boolean flying; if (playerData.doesCacheExist(name)) { StoreInventoryEvent event = new StoreInventoryEvent(player, playerData); @@ -63,6 +64,7 @@ public class LimboCache { } playerGroup = playerData.readCache(name).getGroup(); operator = playerData.readCache(name).getOperator(); + flying = playerData.readCache(name).isFlying(); } else { StoreInventoryEvent event = new StoreInventoryEvent(player); Bukkit.getServer().getPluginManager().callEvent(event); @@ -73,11 +75,12 @@ public class LimboCache { inv = null; arm = null; } - if(player.isOp() ) { + if(player.isOp()) operator = true; - } else { - operator = false; - } + else operator = false; + if(player.isFlying()) + flying = true; + else flying = false; } if(Settings.isForceSurvivalModeEnabled) { @@ -108,7 +111,7 @@ public class LimboCache { } } catch (NullPointerException ex) { } - cache.put(player.getName().toLowerCase(), new LimboPlayer(name, loc, inv, arm, gameMode, operator, playerGroup)); + cache.put(player.getName().toLowerCase(), new LimboPlayer(name, loc, inv, arm, gameMode, operator, playerGroup, flying)); } public void addLimboPlayer(Player player, String group) { diff --git a/src/main/java/uk/org/whoami/authme/cache/limbo/LimboPlayer.java b/src/main/java/uk/org/whoami/authme/cache/limbo/LimboPlayer.java index d4291b23..d95bdf83 100644 --- a/src/main/java/uk/org/whoami/authme/cache/limbo/LimboPlayer.java +++ b/src/main/java/uk/org/whoami/authme/cache/limbo/LimboPlayer.java @@ -30,8 +30,9 @@ public class LimboPlayer { private int gameMode = 0; private boolean operator = false; private String group = null; + private boolean flying = false; - public LimboPlayer(String name, Location loc, ItemStack[] inventory, ItemStack[] armour, int gameMode, boolean operator, String group) { + public LimboPlayer(String name, Location loc, ItemStack[] inventory, ItemStack[] armour, int gameMode, boolean operator, String group, boolean flying) { this.name = name; this.loc = loc; this.inventory = inventory; @@ -39,14 +40,16 @@ public class LimboPlayer { this.gameMode = gameMode; this.operator = operator; this.group = group; + this.flying = flying; } - public LimboPlayer(String name, Location loc, int gameMode, boolean operator, String group) { + public LimboPlayer(String name, Location loc, int gameMode, boolean operator, String group, boolean flying) { this.name = name; this.loc = loc; this.gameMode = gameMode; this.operator = operator; this.group = group; + this.flying = flying; } public LimboPlayer(String name, String group) { @@ -98,4 +101,8 @@ public class LimboPlayer { return messageTaskId; } + public boolean isFlying() { + return flying; + } + } diff --git a/src/main/java/uk/org/whoami/authme/commands/AdminCommand.java b/src/main/java/uk/org/whoami/authme/commands/AdminCommand.java index 17f63b11..e9071059 100644 --- a/src/main/java/uk/org/whoami/authme/commands/AdminCommand.java +++ b/src/main/java/uk/org/whoami/authme/commands/AdminCommand.java @@ -44,6 +44,7 @@ import uk.org.whoami.authme.Utils; import uk.org.whoami.authme.cache.auth.PlayerAuth; import uk.org.whoami.authme.cache.auth.PlayerCache; import uk.org.whoami.authme.converter.FlatToSql; +import uk.org.whoami.authme.converter.FlatToSqlite; import uk.org.whoami.authme.converter.RakamakConverter; import uk.org.whoami.authme.converter.xAuthToFlat; import uk.org.whoami.authme.datasource.DataSource; @@ -110,6 +111,7 @@ public class AdminCommand implements CommandExecutor { long days = Long.parseLong(args[1]) * 86400000; long until = new Date().getTime() - days; sender.sendMessage("Deleted " + database.purgeDatabase(until) + " user accounts"); + return true; } catch (NumberFormatException e) { sender.sendMessage("Usage: /authme purge "); return true; @@ -286,6 +288,16 @@ public class AdminCommand implements CommandExecutor { } catch (NullPointerException ex) { System.out.println(ex.getMessage()); } + } else if (args[0].equalsIgnoreCase("flattosqlite")) { + try { + String s = FlatToSqlite.convert(); + if (sender instanceof Player) + sender.sendMessage(s); + } catch (IOException e) { + e.printStackTrace(); + } catch (NullPointerException ex) { + System.out.println(ex.getMessage()); + } } else if (args[0].equalsIgnoreCase("xauthimport")) { xAuthToFlat converter = new xAuthToFlat(plugin, database); if (converter.convert(sender)) { diff --git a/src/main/java/uk/org/whoami/authme/commands/LogoutCommand.java b/src/main/java/uk/org/whoami/authme/commands/LogoutCommand.java index 05cc1fb0..2197b97c 100644 --- a/src/main/java/uk/org/whoami/authme/commands/LogoutCommand.java +++ b/src/main/java/uk/org/whoami/authme/commands/LogoutCommand.java @@ -90,7 +90,7 @@ public class LogoutCommand implements CommandExecutor { player.getInventory().setContents(new ItemStack[36]); // create cache file for handling lost of inventories on unlogged in status DataFileCache playerData = new DataFileCache(player.getInventory().getContents(),player.getInventory().getArmorContents()); - playerBackup.createCache(name, playerData, LimboCache.getInstance().getLimboPlayer(name).getGroup(),LimboCache.getInstance().getLimboPlayer(name).getOperator()); + playerBackup.createCache(name, playerData, LimboCache.getInstance().getLimboPlayer(name).getGroup(),LimboCache.getInstance().getLimboPlayer(name).getOperator(),LimboCache.getInstance().getLimboPlayer(name).isFlying()); } if (Settings.isTeleportToSpawnEnabled) { Location spawnLoc = player.getWorld().getSpawnLocation(); diff --git a/src/main/java/uk/org/whoami/authme/converter/FlatToSql.java b/src/main/java/uk/org/whoami/authme/converter/FlatToSql.java index 4f153015..3f1485de 100644 --- a/src/main/java/uk/org/whoami/authme/converter/FlatToSql.java +++ b/src/main/java/uk/org/whoami/authme/converter/FlatToSql.java @@ -18,16 +18,6 @@ import uk.org.whoami.authme.settings.Settings; */ public class FlatToSql { - public AuthMe instance; - - public FlatToSql (AuthMe instance) { - this.instance = instance; - } - - public FlatToSql getInstance() { - return this; - } - private static String tableName; private static String columnName; private static String columnPassword; @@ -85,7 +75,7 @@ public class FlatToSql { else if (args.length == 7) newline = "INSERT INTO " + tableName + " VALUES (" + i + ", '" + args[0] + "', '" + args[1] + "', '" + args[2] + "', " + args[3] + ", " + args[4] + ", " + args[5] + ", " + args[6] + ", 'world', 'your@email.com');"; else if (args.length == 8) - newline = "INSERT INTO " + tableName + " VALUES (" + i + ", '" + args[0] + "', '" + args[1] + "', '" + args[2] + "', " + args[3] + ", " + args[4] + ", " + args[5] + ", " + args[6] + ", " + args[7] + ", 'your@email.com');"; + newline = "INSERT INTO " + tableName + " VALUES (" + i + ", '" + args[0] + "', '" + args[1] + "', '" + args[2] + "', " + args[3] + ", " + args[4] + ", " + args[5] + ", " + args[6] + ", '" + args[7] + "', 'your@email.com');"; else newline = ""; if (newline != "") diff --git a/src/main/java/uk/org/whoami/authme/converter/FlatToSqlite.java b/src/main/java/uk/org/whoami/authme/converter/FlatToSqlite.java new file mode 100644 index 00000000..d19652d0 --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/converter/FlatToSqlite.java @@ -0,0 +1,198 @@ +package uk.org.whoami.authme.converter; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import uk.org.whoami.authme.AuthMe; +import uk.org.whoami.authme.ConsoleLogger; +import uk.org.whoami.authme.settings.Settings; + +public class FlatToSqlite { + + private static String tableName; + private static String columnName; + private static String columnPassword; + private static String columnIp; + private static String columnLastLogin; + private static String lastlocX; + private static String lastlocY; + private static String lastlocZ; + private static String lastlocWorld; + private static String columnEmail; + private static File source; + private static String database; + private static String columnID; + private static Connection con; + + public static String convert() throws IOException { + database = Settings.getMySQLDatabase; + tableName = Settings.getMySQLTablename; + columnName = Settings.getMySQLColumnName; + columnPassword = Settings.getMySQLColumnPassword; + columnIp = Settings.getMySQLColumnIp; + columnLastLogin = Settings.getMySQLColumnLastLogin; + lastlocX = Settings.getMySQLlastlocX; + lastlocY = Settings.getMySQLlastlocY; + lastlocZ = Settings.getMySQLlastlocZ; + lastlocWorld = Settings.getMySQLlastlocWorld; + columnEmail = Settings.getMySQLColumnEmail; + columnID = Settings.getMySQLColumnId; + ConsoleLogger.info("Converting FlatFile to SQLite ..."); + if (new File(AuthMe.getInstance().getDataFolder() + File.separator + database + ".db").exists()) { + return "The Database " + database + ".db can't be created cause the file already exist"; + } + try { + connect(); + setup(); + } catch (Exception e) { + ConsoleLogger.showError("Problem while trying to convert to sqlite !"); + return "Problem while trying to convert to sqlite !"; + } + try { + source = new File(AuthMe.getInstance().getDataFolder() + File.separator + "auths.db"); + source.createNewFile(); + BufferedReader br = new BufferedReader(new FileReader(source)); + String line; + int i = 1; + String newline; + while ((line = br.readLine()) != null) { + String[] args = line.split(":"); + if (args.length == 4) + newline = "INSERT INTO " + tableName + " VALUES (" + i + ", '" + args[0] + "', '" + args[1] + "', '" + args[2] + "', " + args[3] + ", 0, 0, 0, 'world', 'your@email.com');"; + else if (args.length == 7) + newline = "INSERT INTO " + tableName + " VALUES (" + i + ", '" + args[0] + "', '" + args[1] + "', '" + args[2] + "', " + args[3] + ", " + args[4] + ", " + args[5] + ", " + args[6] + ", 'world', 'your@email.com');"; + else if (args.length == 8) + newline = "INSERT INTO " + tableName + " VALUES (" + i + ", '" + args[0] + "', '" + args[1] + "', '" + args[2] + "', " + args[3] + ", " + args[4] + ", " + args[5] + ", " + args[6] + ", '" + args[7] + "', 'your@email.com');"; + else + newline = ""; + if (newline != "") + saveAuth(newline); + i = i + 1; + } + br.close(); + ConsoleLogger.info("The FlatFile has been converted to " + database + ".db file"); + close(); + return ("The FlatFile has been converted to " + database + ".db file"); + } catch (FileNotFoundException ex) { + ConsoleLogger.showError(ex.getMessage()); + } catch (IOException ex) { + ConsoleLogger.showError(ex.getMessage()); + } + return "Errors appears while trying to convert to SQLite"; + } + + private synchronized static void connect() throws ClassNotFoundException, SQLException { + Class.forName("org.sqlite.JDBC"); + ConsoleLogger.info("SQLite driver loaded"); + con = DriverManager.getConnection("jdbc:sqlite:plugins/AuthMe/"+database+".db"); + } + + private synchronized static void setup() throws SQLException { + Statement st = null; + ResultSet rs = null; + try { + st = con.createStatement(); + st.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " (" + + columnID + " INTEGER AUTO_INCREMENT," + + columnName + " VARCHAR(255) NOT NULL UNIQUE," + + columnPassword + " VARCHAR(255) NOT NULL," + + columnIp + " VARCHAR(40) NOT NULL," + + columnLastLogin + " BIGINT," + + lastlocX + " smallint(6) DEFAULT '0'," + + lastlocY + " smallint(6) DEFAULT '0'," + + lastlocZ + " smallint(6) DEFAULT '0'," + + lastlocWorld + " VARCHAR(255) DEFAULT 'world'," + + columnEmail + " VARCHAR(255) DEFAULT 'your@email.com'," + + "CONSTRAINT table_const_prim PRIMARY KEY (" + columnID + "));"); + rs = con.getMetaData().getColumns(null, null, tableName, columnPassword); + if (!rs.next()) { + st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + + columnPassword + " VARCHAR(255) NOT NULL;"); + } + rs.close(); + rs = con.getMetaData().getColumns(null, null, tableName, columnIp); + if (!rs.next()) { + st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + + columnIp + " VARCHAR(40) NOT NULL;"); + } + rs.close(); + rs = con.getMetaData().getColumns(null, null, tableName, columnLastLogin); + if (!rs.next()) { + st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + + columnLastLogin + " BIGINT;"); + } + rs.close(); + rs = con.getMetaData().getColumns(null, null, tableName, lastlocX); + if (!rs.next()) { + st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + lastlocX + " smallint(6) NOT NULL DEFAULT '0'; " + + "ALTER TABLE " + tableName + " ADD COLUMN " + lastlocY + " smallint(6) NOT NULL DEFAULT '0'; " + + "ALTER TABLE " + tableName + " ADD COLUMN " + lastlocZ + " smallint(6) NOT NULL DEFAULT '0';"); + } + rs.close(); + rs = con.getMetaData().getColumns(null, null, tableName, lastlocWorld); + if (!rs.next()) { + st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + lastlocWorld + " VARCHAR(255) NOT NULL DEFAULT 'world' AFTER " + lastlocZ + ";"); + } + rs.close(); + rs = con.getMetaData().getColumns(null, null, tableName, columnEmail); + if (!rs.next()) { + st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + columnEmail + " VARCHAR(255) DEFAULT 'your@email.com';"); + } + } finally { + close(rs); + close(st); + } + ConsoleLogger.info("SQLite Setup finished"); + } + + private static synchronized boolean saveAuth(String s) { + PreparedStatement pst = null; + try { + pst = con.prepareStatement(s); + pst.executeUpdate(); + } catch (SQLException e) { + ConsoleLogger.showError(e.getMessage()); + return false; + } finally { + close(pst); + } + return true; + } + + private static void close(Statement st) { + if (st != null) { + try { + st.close(); + } catch (SQLException ex) { + ConsoleLogger.showError(ex.getMessage()); + } + } + } + + private static void close(ResultSet rs) { + if (rs != null) { + try { + rs.close(); + } catch (SQLException ex) { + ConsoleLogger.showError(ex.getMessage()); + } + } + } + + public synchronized static void close() { + try { + con.close(); + } catch (SQLException ex) { + ConsoleLogger.showError(ex.getMessage()); + } + } +} diff --git a/src/main/java/uk/org/whoami/authme/datasource/CacheDataSource.java b/src/main/java/uk/org/whoami/authme/datasource/CacheDataSource.java index 6b61fcc8..234d84f1 100644 --- a/src/main/java/uk/org/whoami/authme/datasource/CacheDataSource.java +++ b/src/main/java/uk/org/whoami/authme/datasource/CacheDataSource.java @@ -182,4 +182,5 @@ public class CacheDataSource implements DataSource { } } } + } diff --git a/src/main/java/uk/org/whoami/authme/datasource/MiniConnectionPoolManager.java b/src/main/java/uk/org/whoami/authme/datasource/MiniConnectionPoolManager.java index d0ed6d08..306031c3 100644 --- a/src/main/java/uk/org/whoami/authme/datasource/MiniConnectionPoolManager.java +++ b/src/main/java/uk/org/whoami/authme/datasource/MiniConnectionPoolManager.java @@ -37,14 +37,18 @@ public class MiniConnectionPoolManager { private ConnectionPoolDataSource dataSource; private int maxConnections; -private long timeoutMs = 100 * 1000L; +private long timeoutMs; private PrintWriter logWriter; private Semaphore semaphore; -private LinkedList recycledConnections; -private int activeConnections; private PoolConnectionEventListener poolConnectionEventListener; -private boolean isDisposed; -private boolean doPurgeConnection; + +// The following variables must only be accessed within synchronized blocks. +// @GuardedBy("this") could by used in the future. +private LinkedList recycledConnections; // list of inactive PooledConnections +private int activeConnections; // number of active (open) connections of this pool +private boolean isDisposed; // true if this connection pool has been disposed +private boolean doPurgeConnection; // flag to purge the connection currently beeing closed instead of recycling it +private PooledConnection connectionInTransition; // a PooledConnection which is currently within a PooledConnection.getConnection() call, or null /** * Thrown in {@link #getConnection()} or {@link #getValidConnection()} when no free connection becomes @@ -66,7 +70,7 @@ public static class TimeoutException extends RuntimeException { * the maximum number of connections. */ public MiniConnectionPoolManager (ConnectionPoolDataSource dataSource, int maxConnections) { - this(dataSource, maxConnections, 100); } + this(dataSource, maxConnections, 60); } /** * Constructs a MiniConnectionPoolManager object. @@ -146,15 +150,23 @@ private Connection getConnection2 (long timeoutMs) throws SQLException { private synchronized Connection getConnection3() throws SQLException { if (isDisposed) { - throw new IllegalStateException("Connection pool has been disposed."); } // test again with lock + throw new IllegalStateException("Connection pool has been disposed."); } PooledConnection pconn; if (!recycledConnections.isEmpty()) { pconn = recycledConnections.remove(); } else { pconn = dataSource.getPooledConnection(); pconn.addConnectionEventListener(poolConnectionEventListener); } - Connection conn = pconn.getConnection(); - activeConnections++; + Connection conn; + try { + // The JDBC driver may call ConnectionEventListener.connectionErrorOccurred() + // from within PooledConnection.getConnection(). To detect this within + // disposeConnection(), we temporarily set connectionInTransition. + connectionInTransition = pconn; + activeConnections++; + conn = pconn.getConnection(); } + finally { + connectionInTransition = null; } assertInnerState(); return conn; } @@ -171,7 +183,6 @@ private synchronized Connection getConnection3() throws SQLException { *

This method is slower than {@link #getConnection()} because the JDBC * driver has to send an extra command to the database server to test the connection. * -* *

This method requires Java 1.6 or newer. * * @throws TimeoutException @@ -189,17 +200,12 @@ public Connection getValidConnection() { if (triesWithoutDelay <= 0) { triesWithoutDelay = 0; try { - Thread.sleep(250); - } catch (InterruptedException e) { - throw new RuntimeException("Interrupted while waiting for a valid database connection.", e); - } - } + Thread.sleep(250); } + catch (InterruptedException e) { + throw new RuntimeException("Interrupted while waiting for a valid database connection.", e); }} time = System.currentTimeMillis(); if (time >= timeoutTime) { - throw new TimeoutException("Timeout while waiting for a valid database connection."); - } - } -} + throw new TimeoutException("Timeout while waiting for a valid database connection."); }}} private Connection getValidConnection2 (long time, long timeoutTime) { long rtime = Math.max(1, timeoutTime - time); @@ -241,7 +247,7 @@ private synchronized void recycleConnection (PooledConnection pconn) { disposeConnection(pconn); return; } if (activeConnections <= 0) { - throw new AssertionError(); } + throw new AssertionError("AuthMeDatabaseError"); } activeConnections--; semaphore.release(); recycledConnections.add(pconn); @@ -249,11 +255,12 @@ private synchronized void recycleConnection (PooledConnection pconn) { private synchronized void disposeConnection (PooledConnection pconn) { pconn.removeConnectionEventListener(poolConnectionEventListener); - if (!recycledConnections.remove(pconn)) { - // If the PooledConnection is not in the recycledConnections list, + if (!recycledConnections.remove(pconn) && pconn != connectionInTransition) { + // If the PooledConnection is not in the recycledConnections list + // and is not currently within a PooledConnection.getConnection() call, // we assume that the connection was active. if (activeConnections <= 0) { - throw new AssertionError(); } + throw new AssertionError("AuthMeDatabaseError"); } activeConnections--; semaphore.release(); } closeConnectionAndIgnoreException(pconn); @@ -274,13 +281,13 @@ private void log (String msg) { logWriter.println(s); }} catch (Exception e) {}} -private void assertInnerState() { +private synchronized void assertInnerState() { if (activeConnections < 0) { - throw new AssertionError(); } + throw new AssertionError("AuthMeDatabaseError"); } if (activeConnections + recycledConnections.size() > maxConnections) { - throw new AssertionError(); } + throw new AssertionError("AuthMeDatabaseError"); } if (activeConnections + semaphore.availablePermits() > maxConnections) { - throw new AssertionError(); }} + throw new AssertionError("AuthMeDatabaseError"); }} private class PoolConnectionEventListener implements ConnectionEventListener { public void connectionClosed (ConnectionEvent event) { diff --git a/src/main/java/uk/org/whoami/authme/datasource/MySQLDataSource.java b/src/main/java/uk/org/whoami/authme/datasource/MySQLDataSource.java index 4e89bb2f..cd07d85f 100644 --- a/src/main/java/uk/org/whoami/authme/datasource/MySQLDataSource.java +++ b/src/main/java/uk/org/whoami/authme/datasource/MySQLDataSource.java @@ -26,6 +26,7 @@ import java.sql.Statement; import java.util.ArrayList; import java.util.List; +import uk.org.whoami.authme.AuthMe; import uk.org.whoami.authme.ConsoleLogger; import uk.org.whoami.authme.cache.auth.PlayerAuth; import uk.org.whoami.authme.datasource.MiniConnectionPoolManager.TimeoutException; @@ -97,7 +98,7 @@ public class MySQLDataSource implements DataSource { Statement st = null; ResultSet rs = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); st = con.createStatement(); st.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " (" + columnID + " INTEGER AUTO_INCREMENT," @@ -157,7 +158,7 @@ public class MySQLDataSource implements DataSource { PreparedStatement pst = null; ResultSet rs = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnName + "=?;"); @@ -183,7 +184,7 @@ public class MySQLDataSource implements DataSource { PreparedStatement pst = null; ResultSet rs = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnName + "=?;"); pst.setString(1, user); @@ -221,7 +222,7 @@ public class MySQLDataSource implements DataSource { Connection con = null; PreparedStatement pst = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); if ((columnSalt.isEmpty() || columnSalt == null) && (auth.getSalt().isEmpty() || auth.getSalt() == null)) { pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword + "," + columnIp + "," + columnLastLogin + ") VALUES (?,?,?,?);"); pst.setString(1, auth.getNickname()); @@ -264,7 +265,7 @@ public class MySQLDataSource implements DataSource { Connection con = null; PreparedStatement pst = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("UPDATE " + tableName + " SET " + columnPassword + "=? WHERE " + columnName + "=?;"); pst.setString(1, auth.getHash()); pst.setString(2, auth.getNickname()); @@ -287,7 +288,7 @@ public class MySQLDataSource implements DataSource { Connection con = null; PreparedStatement pst = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("UPDATE " + tableName + " SET " + columnIp + "=?, " + columnLastLogin + "=? WHERE " + columnName + "=?;"); pst.setString(1, auth.getIp()); pst.setLong(2, auth.getLastLogin()); @@ -311,7 +312,7 @@ public class MySQLDataSource implements DataSource { Connection con = null; PreparedStatement pst = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + columnLastLogin + " countIp = new ArrayList(); try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnIp + "=?;"); pst.setString(1, auth.getIp()); @@ -532,7 +533,7 @@ public class MySQLDataSource implements DataSource { ResultSet rs = null; List countIp = new ArrayList(); try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnIp + "=?;"); pst.setString(1, ip); @@ -561,7 +562,7 @@ public class MySQLDataSource implements DataSource { ResultSet rs = null; List countEmail = new ArrayList(); try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnEmail + "=?;"); pst.setString(1, email); @@ -589,7 +590,7 @@ public class MySQLDataSource implements DataSource { PreparedStatement pst = null; try { for (String name : banned) { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + columnName + "=?;"); pst.setString(1, name); pst.executeUpdate(); @@ -602,4 +603,55 @@ public class MySQLDataSource implements DataSource { } } + private synchronized Connection makeSureConnectionIsReady() { + Connection con = null; + try { + con = conPool.getValidConnection(); + } catch (Exception te) { + try { + con = null; + reconnect(); + } catch (Exception e) { + ConsoleLogger.showError(e.getMessage()); + if (Settings.isStopEnabled) { + ConsoleLogger.showError("Can't reconnect to MySQL database... Please check your MySQL informations ! SHUTDOWN..."); + AuthMe.getInstance().getServer().shutdown(); + } + if (!Settings.isStopEnabled) + AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance()); + } + } catch (AssertionError ae) { + // Make sure assertionerror is caused by the connectionpoolmanager, else re-throw it + if (!ae.getMessage().equalsIgnoreCase("AuthMeDatabaseError")) + throw new AssertionError(ae.getMessage()); + try { + con = null; + reconnect(); + } catch (Exception e) { + ConsoleLogger.showError(e.getMessage()); + if (Settings.isStopEnabled) { + ConsoleLogger.showError("Can't reconnect to MySQL database... Please check your MySQL informations ! SHUTDOWN..."); + AuthMe.getInstance().getServer().shutdown(); + } + if (!Settings.isStopEnabled) + AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance()); + } + } + if (con == null) + con = conPool.getValidConnection(); + return con; + } + + private synchronized void reconnect() throws ClassNotFoundException, SQLException, TimeoutException { + conPool.dispose(); + Class.forName("com.mysql.jdbc.Driver"); + MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource(); + dataSource.setDatabaseName(database); + dataSource.setServerName(host); + dataSource.setPort(Integer.parseInt(port)); + dataSource.setUser(username); + dataSource.setPassword(password); + conPool = new MiniConnectionPoolManager(dataSource, 10); + ConsoleLogger.info("ConnectionPool was unavailable... Reconnected!"); + } } diff --git a/src/main/java/uk/org/whoami/authme/datasource/SqliteDataSource.java b/src/main/java/uk/org/whoami/authme/datasource/SqliteDataSource.java index afc5f842..074edc72 100644 --- a/src/main/java/uk/org/whoami/authme/datasource/SqliteDataSource.java +++ b/src/main/java/uk/org/whoami/authme/datasource/SqliteDataSource.java @@ -57,7 +57,6 @@ public class SqliteDataSource implements DataSource { Class.forName("org.sqlite.JDBC"); ConsoleLogger.info("SQLite driver loaded"); this.con = DriverManager.getConnection("jdbc:sqlite:plugins/AuthMe/"+database+".db"); - } private synchronized void setup() throws SQLException { diff --git a/src/main/java/uk/org/whoami/authme/listener/AuthMeEntityListener.java b/src/main/java/uk/org/whoami/authme/listener/AuthMeEntityListener.java index 3ab16176..fcf8fbf0 100644 --- a/src/main/java/uk/org/whoami/authme/listener/AuthMeEntityListener.java +++ b/src/main/java/uk/org/whoami/authme/listener/AuthMeEntityListener.java @@ -83,8 +83,8 @@ public class AuthMeEntityListener implements Listener{ if (event.isCancelled()) { return; } - - Entity entity = event.getEntity(); + if (event.getTarget() == null) return; + Entity entity = event.getTarget(); if (!(entity instanceof Player)) { return; } @@ -101,7 +101,7 @@ public class AuthMeEntityListener implements Listener{ return; } } - + event.setTarget(null); event.setCancelled(true); } diff --git a/src/main/java/uk/org/whoami/authme/listener/AuthMePlayerListener.java b/src/main/java/uk/org/whoami/authme/listener/AuthMePlayerListener.java index 4bcbe14e..27bc0be9 100644 --- a/src/main/java/uk/org/whoami/authme/listener/AuthMePlayerListener.java +++ b/src/main/java/uk/org/whoami/authme/listener/AuthMePlayerListener.java @@ -94,60 +94,52 @@ public class AuthMePlayerListener implements Listener { @EventHandler(priority = EventPriority.LOWEST) public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) { - if (event.isCancelled() || event.getPlayer() == null) { + if (event.isCancelled() || event.getPlayer() == null) return; - } Player player = event.getPlayer(); String name = player.getName().toLowerCase(); - if (Utils.getInstance().isUnrestricted(player)) { + if (Utils.getInstance().isUnrestricted(player)) return; - } - if (PlayerCache.getInstance().isAuthenticated(name)) { + if (PlayerCache.getInstance().isAuthenticated(name)) return; - } - if (!data.isAuthAvailable(name)) { - if (!Settings.isForcedRegistrationEnabled) { + if (!data.isAuthAvailable(name)) + if (!Settings.isForcedRegistrationEnabled) return; - } - } String msg = event.getMessage(); //WorldEdit GUI Shit - if (msg.equalsIgnoreCase("/worldedit cui")) { + if (msg.equalsIgnoreCase("/worldedit cui")) return; - } String cmd = msg.split(" ")[0]; - if (cmd.equalsIgnoreCase("/login") || cmd.equalsIgnoreCase("/register") || cmd.equalsIgnoreCase("/passpartu") || cmd.equalsIgnoreCase("/l") || cmd.equalsIgnoreCase("/reg") || cmd.equalsIgnoreCase("/email") || cmd.equalsIgnoreCase("/captcha")) { + if (cmd.equalsIgnoreCase("/login") || cmd.equalsIgnoreCase("/register") || cmd.equalsIgnoreCase("/passpartu") || cmd.equalsIgnoreCase("/l") || cmd.equalsIgnoreCase("/reg") || cmd.equalsIgnoreCase("/email") || cmd.equalsIgnoreCase("/captcha")) return; - } - if (Settings.allowCommands.contains(cmd)) { + if (Settings.useEssentialsMotd && cmd.equalsIgnoreCase("/motd")) return; - } + if (Settings.allowCommands.contains(cmd)) + return; + event.setMessage("/notloggedin"); event.setCancelled(true); } @EventHandler( priority = EventPriority.NORMAL) public void onPlayerNormalChat(AsyncPlayerChatEvent event) { - if (event.isCancelled() || event.getPlayer() == null) { + if (event.isCancelled() || event.getPlayer() == null) return; - } final Player player = event.getPlayer(); final String name = player.getName().toLowerCase(); - if (Utils.getInstance().isUnrestricted(player)) { + if (Utils.getInstance().isUnrestricted(player)) return; - } - if (PlayerCache.getInstance().isAuthenticated(name)) { + if (PlayerCache.getInstance().isAuthenticated(name)) return; - } String cmd = event.getMessage().split(" ")[0]; @@ -266,7 +258,6 @@ public class AuthMePlayerListener implements Listener { String cmd = event.getMessage().split(" ")[0]; if (!Settings.isChatAllowed && !(Settings.allowCommands.contains(cmd))) { - //System.out.println("debug chat: chat isnt allowed"); event.setCancelled(true); return; } @@ -702,8 +693,7 @@ public class AuthMePlayerListener implements Listener { plugin.getServer().banIP(ip); return; } - - if (data.isAuthAvailable(name)) { + if (data.isAuthAvailable(name)) { if (Settings.isSessionsEnabled) { PlayerAuth auth = data.getAuth(name); long timeout = Settings.getSessionTimeout * 60000; @@ -725,6 +715,12 @@ public class AuthMePlayerListener implements Listener { player.kickPlayer(m._("unvalid_session")); return; } else if (auth.getNickname().equalsIgnoreCase(name)){ + if (Settings.isForceSurvivalModeEnabled && !Settings.forceOnlyAfterLogin) + sched.scheduleSyncDelayedTask(plugin, new Runnable() { + public void run() { + e.getPlayer().setGameMode(GameMode.SURVIVAL); + } + }); //Player change his IP between 2 relog-in PlayerCache.getInstance().removePlayer(name); LimboCache.getInstance().addLimboPlayer(player , utils.removeAll(player)); @@ -739,12 +735,16 @@ public class AuthMePlayerListener implements Listener { PlayerCache.getInstance().removePlayer(name); LimboCache.getInstance().addLimboPlayer(player , utils.removeAll(player)); } - } + } // isent in session or session was ended correctly - LimboCache.getInstance().addLimboPlayer(player); + if (Settings.isForceSurvivalModeEnabled && !Settings.forceOnlyAfterLogin) + e.getPlayer().setGameMode(GameMode.SURVIVAL); + LimboCache.getInstance().updateLimboPlayer(player); DataFileCache dataFile = new DataFileCache(LimboCache.getInstance().getLimboPlayer(name).getInventory(),LimboCache.getInstance().getLimboPlayer(name).getArmour()); - playerBackup.createCache(name, dataFile, LimboCache.getInstance().getLimboPlayer(name).getGroup(),LimboCache.getInstance().getLimboPlayer(name).getOperator()); - } else { + playerBackup.createCache(name, dataFile, LimboCache.getInstance().getLimboPlayer(name).getGroup(),LimboCache.getInstance().getLimboPlayer(name).getOperator(),LimboCache.getInstance().getLimboPlayer(name).isFlying()); + } else { + if (Settings.isForceSurvivalModeEnabled && !Settings.forceOnlyAfterLogin) + e.getPlayer().setGameMode(GameMode.SURVIVAL); if(!Settings.unRegisteredGroup.isEmpty()){ utils.setGroup(player, Utils.groupType.UNREGISTERED); } @@ -752,6 +752,7 @@ public class AuthMePlayerListener implements Listener { return; } } + if(Settings.protectInventoryBeforeLogInEnabled) { try { LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(player.getName().toLowerCase()); @@ -774,6 +775,7 @@ public class AuthMePlayerListener implements Listener { player.teleport(tpEvent.getTo()); } } + placePlayerSafely(player, spawnLoc); String msg = ""; if(Settings.emailRegistration) { msg = data.isAuthAvailable(name) ? m._("login_msg") : m._("reg_email_msg"); @@ -792,22 +794,23 @@ public class AuthMePlayerListener implements Listener { LimboCache.getInstance().addLimboPlayer(player); if(player.isOp()) player.setOp(false); + player.setAllowFlight(true); + player.setFlying(true); BukkitTask msgT = sched.runTask(plugin, new MessageTask(plugin, name, msg, msgInterval)); LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT.getTaskId()); - if (Settings.isForceSurvivalModeEnabled) - sched.scheduleSyncDelayedTask(plugin, new Runnable() { - public void run() { - e.getPlayer().setGameMode(GameMode.SURVIVAL); - } - }); - placePlayerSafely(player, spawnLoc); + player.setNoDamageTicks(Settings.getRegistrationTimeout * 20); + if (Settings.useEssentialsMotd) + player.performCommand("motd"); } private void placePlayerSafely(Player player, Location spawnLoc) { + if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) + return; Block b = player.getLocation().getBlock(); - if (b.getType() == Material.PORTAL || b.getType() == Material.ENDER_PORTAL) { + if (b.getType() == Material.PORTAL || b.getType() == Material.ENDER_PORTAL || b.getType() == Material.LAVA || b.getType() == Material.STATIONARY_LAVA) { player.sendMessage(m._("unsafe_spawn")); player.teleport(spawnLoc); + return; } } @@ -856,6 +859,9 @@ public class AuthMePlayerListener implements Listener { } utils.addNormal(player, limbo.getGroup()); player.setOp(limbo.getOperator()); + if (player.getGameMode() != GameMode.CREATIVE) + player.setAllowFlight(limbo.isFlying()); + player.setFlying(limbo.isFlying()); this.plugin.getServer().getScheduler().cancelTask(limbo.getTimeoutTaskId()); LimboCache.getInstance().deleteLimboPlayer(name); if(playerBackup.doesCacheExist(name)) { @@ -900,7 +906,7 @@ public class AuthMePlayerListener implements Listener { String name = player.getName().toLowerCase(); if ((PlayerCache.getInstance().isAuthenticated(name)) && (!player.isDead()) && - (Settings.isSaveQuitLocationEnabled.booleanValue()) && data.isAuthAvailable(name)) { + (Settings.isSaveQuitLocationEnabled) && data.isAuthAvailable(name)) { final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(),loc.getWorld().getName()); try { if (data instanceof Thread) { @@ -919,7 +925,7 @@ public class AuthMePlayerListener implements Listener { if (LimboCache.getInstance().hasLimboPlayer(name)) { LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name); - if (Settings.protectInventoryBeforeLogInEnabled.booleanValue()) { + if (Settings.protectInventoryBeforeLogInEnabled) { try { RestoreInventoryEvent ev = new RestoreInventoryEvent(player, limbo.getInventory(), limbo.getArmour()); plugin.getServer().getPluginManager().callEvent(ev); @@ -943,7 +949,9 @@ public class AuthMePlayerListener implements Listener { } this.utils.addNormal(player, limbo.getGroup()); player.setOp(limbo.getOperator()); - + if (player.getGameMode() != GameMode.CREATIVE) + player.setAllowFlight(limbo.isFlying()); + player.setFlying(limbo.isFlying()); this.plugin.getServer().getScheduler().cancelTask(limbo.getTimeoutTaskId()); LimboCache.getInstance().deleteLimboPlayer(name); if (this.playerBackup.doesCacheExist(name)) { @@ -1190,19 +1198,6 @@ public class AuthMePlayerListener implements Listener { } if (Spawn.getInstance().getLocation() != null && Spawn.getInstance().getLocation().getWorld().equals(player.getWorld())) spawn = Spawn.getInstance().getLocation(); - final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ(),spawn.getWorld().getName()); - try { - if (data instanceof Thread) { - data.updateQuitLoc(auth); - } else { - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){ - @Override - public void run() { - data.updateQuitLoc(auth); - } - }); - } - } catch (NullPointerException npe) { } event.setRespawnLocation(spawn); } diff --git a/src/main/java/uk/org/whoami/authme/security/PasswordSecurity.java b/src/main/java/uk/org/whoami/authme/security/PasswordSecurity.java index f58d74c3..230d5bfc 100644 --- a/src/main/java/uk/org/whoami/authme/security/PasswordSecurity.java +++ b/src/main/java/uk/org/whoami/authme/security/PasswordSecurity.java @@ -28,6 +28,7 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import uk.org.whoami.authme.AuthMe; +import uk.org.whoami.authme.security.pbkdf2.BinTools; import uk.org.whoami.authme.security.pbkdf2.PBKDF2Engine; import uk.org.whoami.authme.security.pbkdf2.PBKDF2Parameters; import uk.org.whoami.authme.settings.Settings; @@ -110,9 +111,10 @@ public class PasswordSecurity { private static String getPBKDF2(String password, String salt) throws NoSuchAlgorithmException { String result = "pbkdf2_sha256$10000$"+salt+"$"; - PBKDF2Parameters params = new PBKDF2Parameters("SHA-256", "UTF-8", salt.getBytes(), 10000); + PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", BinTools.hex2bin(salt), 10000); PBKDF2Engine engine = new PBKDF2Engine(params); - return result + engine.deriveKey(password,57).toString(); + + return result + BinTools.bin2hex(engine.deriveKey(password,64)); } private static String createSalt(int length) throws NoSuchAlgorithmException { @@ -290,7 +292,7 @@ public class PasswordSecurity { String[] line = hash.split("\\$"); String salt = line[2]; String derivedKey = line[3]; - PBKDF2Parameters params = new PBKDF2Parameters("SHA-256", "UTF-8", salt.getBytes(), 10000, derivedKey.getBytes()); + PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", BinTools.hex2bin(salt), 10000, BinTools.hex2bin(derivedKey)); PBKDF2Engine engine = new PBKDF2Engine(params); return engine.verifyKey(password); } diff --git a/src/main/java/uk/org/whoami/authme/settings/Settings.java b/src/main/java/uk/org/whoami/authme/settings/Settings.java index ba1e2323..7e19748e 100644 --- a/src/main/java/uk/org/whoami/authme/settings/Settings.java +++ b/src/main/java/uk/org/whoami/authme/settings/Settings.java @@ -60,7 +60,7 @@ public final class Settings extends YamlConfiguration { getEnablePasswordVerifier, protectInventoryBeforeLogInEnabled, isBackupActivated, isBackupOnStart, isBackupOnStop, enablePasspartu, isStopEnabled, reloadSupport, rakamakUseIp, noConsoleSpam, removePassword, displayOtherAccounts, useCaptcha, emailRegistration, multiverse, notifications, chestshop, bungee, banUnsafeIp, doubleEmailCheck, sessionExpireOnIpChange, - disableSocialSpy, useMultiThreading; + disableSocialSpy, useMultiThreading, forceOnlyAfterLogin, useEssentialsMotd; public static String getNickRegex, getUnloggedinGroup, getMySQLHost, getMySQLPort, getMySQLUsername, getMySQLPassword, getMySQLDatabase, getMySQLTablename, @@ -210,6 +210,8 @@ public void loadConfigOptions() { disableSocialSpy = configFile.getBoolean("Hooks.disableSocialSpy", true); useMultiThreading = configFile.getBoolean("Performances.useMultiThreading", false); bCryptLog2Rounds = configFile.getInt("ExternalBoardOptions.bCryptLog2Round", 10); + forceOnlyAfterLogin = configFile.getBoolean("settings.GameMode.ForceOnlyAfterLogin", false); + useEssentialsMotd = configFile.getBoolean("Hooks.useEssentialsMotd", false); saveDefaults(); } @@ -333,7 +335,9 @@ public static void reloadConfigOptions(YamlConfiguration newConfig) { disableSocialSpy = configFile.getBoolean("Hooks.disableSocialSpy", true); useMultiThreading = configFile.getBoolean("Performances.useMultiThreading", false); bCryptLog2Rounds = configFile.getInt("ExternalBoardOptions.bCryptLog2Round", 10); - } + forceOnlyAfterLogin = configFile.getBoolean("settings.GameMode.ForceOnlyAfterLogin", false); + useEssentialsMotd = configFile.getBoolean("Hooks.useEssentialsMotd", false); +} public void mergeConfig() { if (contains("settings.restrictions.allowedPluginTeleportHandler")) @@ -416,6 +420,10 @@ public void mergeConfig() { set("ExternalBoardOptions.bCryptLog2Round", 10); if(!contains("DataSource.mySQLlastlocWorld")) set("DataSource.mySQLlastlocWorld", "world"); + if(!contains("settings.GameMode.ForceOnlyAfterLogin")) + set("settings.GameMode.ForceOnlyAfterLogin", false); + if(!contains("Hooks.useEssentialsMotd")) + set("Hooks.useEssentialsMotd", false); plugin.getLogger().info("Merge new Config Options if needed.."); plugin.saveConfig(); diff --git a/src/main/java/uk/org/whoami/authme/threads/MySQLThread.java b/src/main/java/uk/org/whoami/authme/threads/MySQLThread.java index c1bdf497..6d08e093 100644 --- a/src/main/java/uk/org/whoami/authme/threads/MySQLThread.java +++ b/src/main/java/uk/org/whoami/authme/threads/MySQLThread.java @@ -113,7 +113,7 @@ public class MySQLThread extends Thread implements DataSource { Statement st = null; ResultSet rs = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); st = con.createStatement(); st.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " (" + columnID + " INTEGER AUTO_INCREMENT," @@ -173,7 +173,7 @@ public class MySQLThread extends Thread implements DataSource { PreparedStatement pst = null; ResultSet rs = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnName + "=?;"); @@ -199,7 +199,7 @@ public class MySQLThread extends Thread implements DataSource { PreparedStatement pst = null; ResultSet rs = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnName + "=?;"); pst.setString(1, user); @@ -237,7 +237,7 @@ public class MySQLThread extends Thread implements DataSource { Connection con = null; PreparedStatement pst = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); if ((columnSalt.isEmpty() || columnSalt == null) && (auth.getSalt().isEmpty() || auth.getSalt() == null)) { pst = con.prepareStatement("INSERT INTO " + tableName + "(" + columnName + "," + columnPassword + "," + columnIp + "," + columnLastLogin + ") VALUES (?,?,?,?);"); pst.setString(1, auth.getNickname()); @@ -280,7 +280,7 @@ public class MySQLThread extends Thread implements DataSource { Connection con = null; PreparedStatement pst = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("UPDATE " + tableName + " SET " + columnPassword + "=? WHERE " + columnName + "=?;"); pst.setString(1, auth.getHash()); pst.setString(2, auth.getNickname()); @@ -303,7 +303,7 @@ public class MySQLThread extends Thread implements DataSource { Connection con = null; PreparedStatement pst = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("UPDATE " + tableName + " SET " + columnIp + "=?, " + columnLastLogin + "=? WHERE " + columnName + "=?;"); pst.setString(1, auth.getIp()); pst.setLong(2, auth.getLastLogin()); @@ -327,7 +327,7 @@ public class MySQLThread extends Thread implements DataSource { Connection con = null; PreparedStatement pst = null; try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + columnLastLogin + " countIp = new ArrayList(); try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnIp + "=?;"); pst.setString(1, auth.getIp()); @@ -548,7 +548,7 @@ public class MySQLThread extends Thread implements DataSource { ResultSet rs = null; List countIp = new ArrayList(); try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnIp + "=?;"); pst.setString(1, ip); @@ -577,7 +577,7 @@ public class MySQLThread extends Thread implements DataSource { ResultSet rs = null; List countEmail = new ArrayList(); try { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + columnEmail + "=?;"); pst.setString(1, email); @@ -605,7 +605,7 @@ public class MySQLThread extends Thread implements DataSource { PreparedStatement pst = null; try { for (String name : banned) { - con = conPool.getValidConnection(); + con = makeSureConnectionIsReady(); pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + columnName + "=?;"); pst.setString(1, name); pst.executeUpdate(); @@ -617,25 +617,46 @@ public class MySQLThread extends Thread implements DataSource { close(con); } } - -/* public synchronized boolean makeSureConnectionIsReady() { + + private synchronized Connection makeSureConnectionIsReady() { + Connection con = null; try { - conPool.getValidConnection(); - return true; - } catch (TimeoutException te) { + con = conPool.getValidConnection(); + } catch (Exception te) { try { + con = null; reconnect(); - } catch (TimeoutException e) { - return false; - } catch (ClassNotFoundException e) { - return false; - } catch (SQLException e) { - return false; + } catch (Exception e) { + ConsoleLogger.showError(e.getMessage()); + if (Settings.isStopEnabled) { + ConsoleLogger.showError("Can't reconnect to MySQL database... Please check your MySQL informations ! SHUTDOWN..."); + AuthMe.getInstance().getServer().shutdown(); + } + if (!Settings.isStopEnabled) + AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance()); + } + } catch (AssertionError ae) { + // Make sure assertionerror is caused by the connectionpoolmanager, else re-throw it + if (!ae.getMessage().equalsIgnoreCase("AuthMeDatabaseError")) + throw new AssertionError(ae.getMessage()); + try { + con = null; + reconnect(); + } catch (Exception e) { + ConsoleLogger.showError(e.getMessage()); + if (Settings.isStopEnabled) { + ConsoleLogger.showError("Can't reconnect to MySQL database... Please check your MySQL informations ! SHUTDOWN..."); + AuthMe.getInstance().getServer().shutdown(); + } + if (!Settings.isStopEnabled) + AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance()); } - return true; } + if (con == null) + con = conPool.getValidConnection(); + return con; } - + private synchronized void reconnect() throws ClassNotFoundException, SQLException, TimeoutException { conPool.dispose(); Class.forName("com.mysql.jdbc.Driver"); @@ -646,6 +667,7 @@ public class MySQLThread extends Thread implements DataSource { dataSource.setUser(username); dataSource.setPassword(password); conPool = new MiniConnectionPoolManager(dataSource, 10); - ConsoleLogger.info("Connection pool reconnected"); - } */ + ConsoleLogger.info("ConnectionPool was unavailable... Reconnected!"); + } + } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 1ac92399..8a438a73 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -63,6 +63,7 @@ settings: GameMode: ForceSurvivalMode: false ResetInventoryIfCreative: false + ForceOnlyAfterLogin: false security: minPasswordLength: 4 unLoggedinGroup: unLoggedinGroup @@ -128,5 +129,7 @@ Hooks: chestshop: true bungeecord: false notifications: true + disableSocialSpy: true + useEssentialsMotd: false Performances: useMultiThreading: false \ No newline at end of file diff --git a/src/main/resources/messages_cz.yml b/src/main/resources/messages_cz.yml index 005e15ab..92ee54e7 100644 --- a/src/main/resources/messages_cz.yml +++ b/src/main/resources/messages_cz.yml @@ -1,36 +1,36 @@ unknown_user: '&cHrac neni registrovan.' not_logged_in: '&cNeprihlasen!' reg_voluntarily: '&cRegistruj se prikazem "/register heslo heslo".' -usage_log: '&cPouziti: "/login vaseheslo".' +usage_log: '&cPouzij: "/login TvojeHeslo".' wrong_pwd: '&cSpatne heslo.' unregistered: '&cUspesna unregistrace!' reg_disabled: '&cRegistrace je zakazana!' valid_session: '&cAutomaticke znovuprihlaseni.' login: '&cUspesne prihlaseni!' user_regged: '&cUzivatelske jmeno je jiz registrovano.' -usage_reg: '&cPouziti: "/register heslo heslo".' +usage_reg: '&cPouzij: "/register heslo heslo".' no_perm: '&cNemas opravneni.' error: '&cVyskytla se chyba kontaktujte admina ...' -login_msg: '&cProsim prihlaste se "/login vaseheslo".' -reg_msg: '&cProsim zaregistrujte se "/register heslo heslo".' -reg_email_msg: '&cPlease register with "/register "' -usage_unreg: '&cPouziti: "/unregister vaseheslo".' +login_msg: '&cProsim prihlas se "/login TvojeHeslo".' +reg_msg: '&cProsim zaregistruj se "/register heslo heslo".' +reg_email_msg: '&cProsim registruj se pomoci "/register "' +usage_unreg: '&cPouzij: "/unregister TvojeHeslo".' pwd_changed: '&cHeslo zmeneno!' user_unknown: '&cUzivatelske jmeno neni registrovano.' reg_only: '&cServer je pouze pro registrovane! Navstivte http://bit.ly/zyEzzS.' -logged_in: '&cJste jiz prihlasen!' +logged_in: '&cSes jiz prihlasen!' logout: '&cOdhlaseni bylo uspesne.' same_nick: '&cNekdo jiz hraje se stejnym nickem.' registered: '&cRegistrace byla uspesna!' reload: '&cPrenacteni AuthMe probehlo uspesne.' timeout: '&cCas na prihlaseni vyprsel!' -unsafe_spawn: '&cVase pozice pri odpojeni byla nebezpecna, teleportuji na spawn!' +unsafe_spawn: '&cTvoje pozice pri odpojeni byla nebezpecna, teleportuji na spawn!' unvalid_session: '&cChybna data pri cteni pockejte do vyprseni.' -max_reg: '&cJiz jste prekrocil(a) limit pro pocet uctu z vasi IP.' +max_reg: '&cJiz jsi prekrocil(a) limit pro pocet uctu z jedne IP.' password_error: '&cHesla se neshoduji!' -pass_len: '&cVase heslo nedosahuje minimalni delky (4).' -vb_nonActiv: '&cVas ucet neni aktivaovany, zkontrolujte si vas E-mail.' -usage_changepassword: '&cPouziti: "/changepassword stareHeslo noveHeslo".' +pass_len: '&cTvoje heslo nedosahuje minimalni delky (4).' +vb_nonActiv: '&cTvuj ucet neni aktivovany, zkontrolujte si vas E-mail.' +usage_changepassword: '&cPouzij: "/changepassword stareHeslo noveHeslo".' name_len: '&cTvuj nick je priliz kratky, nebo priliz dlouhy' regex: '&cTvuj nick obsahuje nepovolene znaky. Pripustne znaky jsou: REG_EX' add_email: '&cPridej prosim svuj email pomoci : /email add TvujEmail TvujEmail' @@ -41,13 +41,13 @@ wrong_captcha: '&cSpatne opsana Captcha, pouzij prosim: /captcha CAPTCHA_TEXT' valid_captcha: '&cZadana captcha je OK !' kick_forvip: '&cA VIP Hrac se pripojil na plny server!' kick_fullserver: '&cServer je plne obsazen, zkus to pozdeji prosim !' -usage_email_add: '&fUsage: /email add ' -usage_email_change: '&fUsage: /email change newEmail> ' -usage_email_recovery: '&fUsage: /email recovery ' -new_email_invalid: '[AuthMe] New email invalid!' -old_email_invalid: '[AuthMe] Old email invalid!' -email_invalid: '[AuthMe] Invalid Email' -email_added: '[AuthMe] Email Added !' -email_confirm: '[AuthMe] Confirm your Email !' -email_changed: '[AuthMe] Email Change !' -email_send: '[AuthMe] Recovery Email Send !' +usage_email_add: '&fPouzij: /email add ' +usage_email_change: '&fPouzij: /email change ' +usage_email_recovery: '&fPouzij: /email recovery ' +new_email_invalid: '[AuthMe] Novy email je chybne zadan!' +old_email_invalid: '[AuthMe] Stary email je chybne zadan!' +email_invalid: '[AuthMe] Nespravny email' +email_added: '[AuthMe] Email pridan !' +email_confirm: '[AuthMe] Potvrd prosim svuj email !' +email_changed: '[AuthMe] Email zmenen !' +email_send: '[AuthMe] Email pro obnoveni hesla odeslan !' diff --git a/src/main/resources/messages_es.yml b/src/main/resources/messages_es.yml index 39aa32e4..b6824ff7 100644 --- a/src/main/resources/messages_es.yml +++ b/src/main/resources/messages_es.yml @@ -40,15 +40,15 @@ recovery_email: '&c¿Olvidaste tu contraseña? Por favor usa /email recovery ' wrong_captcha: '&cCaptcha incorrecto, please use : /captcha EL_CAPTCHA' valid_captcha: '&c¡ Captcha ingresado correctamente !' -kick_forvip: '&cA VIP Player join the full server!' -kick_fullserver: '&cThe server is actually full, Sorry!' -usage_email_add: '&fUsage: /email add ' -usage_email_change: '&fUsage: /email change ' -usage_email_recovery: '&fUsage: /email recovery ' -new_email_invalid: '[AuthMe] New email invalid!' -old_email_invalid: '[AuthMe] Old email invalid!' -email_invalid: '[AuthMe] Invalid Email' -email_added: '[AuthMe] Email Added !' -email_confirm: '[AuthMe] Confirm your Email !' -email_changed: '[AuthMe] Email Change !' -email_send: '[AuthMe] Recovery Email Send !' \ No newline at end of file +kick_forvip: '&cUn jugador VIP ha ingresado al servidor lleno!' +kick_fullserver: '&cEl servidor está lleno, lo sentimos!' +usage_email_add: '&fUso: /email add ' +usage_email_change: '&fUso: /email change ' +usage_email_recovery: '&fUso: /email recovery ' +new_email_invalid: '[AuthMe] Nuevo email inválido!' +old_email_invalid: '[AuthMe] Email anterior inválido!' +email_invalid: '[AuthMe] Email inválido' +email_added: '[AuthMe] Email agregado !' +email_confirm: '[AuthMe] Confirma tu Email !' +email_changed: '[AuthMe] Email cambiado !' +email_send: '[AuthMe] Correo de recuperación enviado !' diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 37882aa7..43328a2d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,9 +1,9 @@ name: AuthMe author: Xephi59 -website: http://www.multiplayer-italia.com/ +website: http://dev.bukkit.org/bukkit-plugins/authme-reloaded/ description: AuthMe prevents people, which aren't logged in, from doing stuff like placing blocks, moving, typing commands or seeing the inventory of the current player. main: uk.org.whoami.authme.AuthMe -version: 2.9.3 +version: 2.9.4 softdepend: [Vault, ChestShop, Spout, Multiverse-Core, Notifications, Citizens, CombatTag, Essentials, EssentialsSpawn] commands: register: @@ -137,4 +137,7 @@ permissions: default: op authme.admin.purgebannedplayers: description: Purge banned players + default: op + authme.admin.flattosqlite: + description: Convert File to Sqlite method default: op \ No newline at end of file