diff --git a/pom.xml b/pom.xml index 4c8bab4e0..84209ab08 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ - 2.9.2 + 2.9.3 org.bukkit diff --git a/src/main/java/uk/org/whoami/authme/Management.java b/src/main/java/uk/org/whoami/authme/Management.java index 0525a2344..b1df8ba5b 100644 --- a/src/main/java/uk/org/whoami/authme/Management.java +++ b/src/main/java/uk/org/whoami/authme/Management.java @@ -134,7 +134,7 @@ public class Management { .getLimboPlayer(name); final PlayerAuth getAuth = database.getAuth(name); if (limbo != null) { - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -161,7 +161,7 @@ public class Management { } }); } else { - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -189,7 +189,7 @@ public class Management { .contains(player.getWorld() .getName())) { final Location spawnL = spawnLoc; - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -222,7 +222,7 @@ public class Management { } }); } else { - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -244,7 +244,7 @@ public class Management { }); } - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -256,7 +256,7 @@ public class Management { if (Settings.protectInventoryBeforeLogInEnabled && player.hasPlayedBefore()) { - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -312,7 +312,7 @@ public class Management { pllog.save(); } catch (NullPointerException ex) { } - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -343,7 +343,7 @@ public class Management { "[AuthMe] " + player.getName() + " logged in!")); } - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -359,7 +359,7 @@ public class Management { try { final int gm = AuthMePlayerListener.gameMode .get(name); - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -369,7 +369,7 @@ public class Management { }); } catch (NullPointerException npe) { } - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -393,7 +393,7 @@ public class Management { .getLimboPlayer(name); if (limbo != null) { - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -428,7 +428,7 @@ public class Management { database.getAuth(name) .getQuitLocZ() + 0.5D); - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -448,7 +448,7 @@ public class Management { } }); } else { - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -473,7 +473,7 @@ public class Management { && Settings.getForcedWorlds.contains(player .getWorld().getName())) { final Location spawnL = spawnLoc; - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -510,7 +510,7 @@ public class Management { database.getAuth(name).getQuitLocX() + 0.5D, database.getAuth(name).getQuitLocY() + 0.5D, database.getAuth(name).getQuitLocZ() + 0.5D); - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -528,7 +528,7 @@ public class Management { } }); } else { - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -547,7 +547,7 @@ public class Management { }); } - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -559,7 +559,7 @@ public class Management { if (Settings.protectInventoryBeforeLogInEnabled && player.hasPlayedBefore()) { - Bukkit.getScheduler().runTask(plugin, + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -612,7 +612,7 @@ public class Management { pllog.save(); } catch (NullPointerException ex) { } - Bukkit.getScheduler().runTask(plugin, new Runnable() { + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { Bukkit.getServer() @@ -638,7 +638,7 @@ public class Management { "[AuthMe] " + player.getName() + " logged in!")); } - Bukkit.getScheduler().runTask(plugin, new Runnable() { + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { player.saveData(); 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 00879592c..976bb37e2 100644 --- a/src/main/java/uk/org/whoami/authme/api/API.java +++ b/src/main/java/uk/org/whoami/authme/api/API.java @@ -11,7 +11,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import uk.org.whoami.authme.AuthMe; -import uk.org.whoami.authme.ConsoleLogger; import uk.org.whoami.authme.Utils; import uk.org.whoami.authme.cache.auth.PlayerAuth; import uk.org.whoami.authme.cache.auth.PlayerCache; @@ -73,65 +72,9 @@ public class API { return Utils.getInstance().isUnrestricted(player); } - public static boolean isChatAllowed() { - return Settings.isChatAllowed; - } - - public static boolean isAllowRestrictedIp() { - return Settings.isAllowRestrictedIp; - } - - public static boolean isBackupActivated() { - return Settings.isBackupActivated; - } - - public static boolean isForceSpawnLocOnJoinEnabled() { - return Settings.isForceSpawnLocOnJoinEnabled; - } - - public static DataSourceType getDataSource() { - return Settings.getDataSource; - } - - public static int getMovementRadius() { - return Settings.getMovementRadius; - } - - public static List getJoinPermissions() { - return Settings.getJoinPermissions; - } - - public static Boolean isPasspartuEnable() { - return Settings.enablePasspartu; - } - - public static String getcUnrestrictedName() { - return Settings.getcUnrestrictedName; - } - - public static Boolean getEnablePasswordVerifier() { - return Settings.getEnablePasswordVerifier; - } - - public static int getMaxNickLength() { - return Settings.getMaxNickLength; - } - - public static int getMinNickLength() { - return Settings.getMinNickLength; - } - - public static Array getLastLocationColumns() { - Array columns = null; - Array.set(columns, 0, Settings.getMySQLlastlocX); - Array.set(columns, 1, Settings.getMySQLlastlocY); - Array.set(columns, 2, Settings.getMySQLlastlocZ); - return columns; - } - public static Location getLastLocation(Player player) { try { - PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName()); + PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName().toLowerCase()); if (auth != null) { Location loc = new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY() , auth.getQuitLocZ()); @@ -145,30 +88,6 @@ public class API { } } - public static String getNickRegex() { - return Settings.getNickRegex; - } - - public static int getPasswordMinLen() { - return Settings.getPasswordMinLen; - } - - public static HashAlgorithm getPasswordHash() { - return Settings.getPasswordHash; - } - - public static int getRegistrationTimeout() { - return Settings.getRegistrationTimeout; - } - - public static int getSessionTimeout() { - return Settings.getSessionTimeout; - } - - public static String getUnloggedinGroup() { - return Settings.getUnloggedinGroup; - } - public static void setPlayerInventory(Player player, ItemStack[] content, ItemStack[] armor) { try { player.getInventory().setContents(content); @@ -214,7 +133,7 @@ public class API { try { String name = playerName.toLowerCase(); String hash = PasswordSecurity.getHash(Settings.getPasswordHash, password, name); - if (database.isAuthAvailable(name)) { + if (isRegistered(name)) { return false; } PlayerAuth auth = new PlayerAuth(name, hash, "198.18.0.1", 0); diff --git a/src/main/java/uk/org/whoami/authme/cache/auth/PlayerAuth.java b/src/main/java/uk/org/whoami/authme/cache/auth/PlayerAuth.java index de95552ab..c4016ef6f 100644 --- a/src/main/java/uk/org/whoami/authme/cache/auth/PlayerAuth.java +++ b/src/main/java/uk/org/whoami/authme/cache/auth/PlayerAuth.java @@ -220,5 +220,13 @@ public class PlayerAuth { public String getWorld() { return world; } + + @Override + public String toString() { + String s = "Player : " + nickname + " ! IP : " + ip + " ! LastLogin : " + lastLogin + " ! LastPosition : " + x + "," + y + "," + z + "," + world + + " ! Email : " + email + " ! Hash : " + hash + " ! Salt : " + salt; + return s; + + } } diff --git a/src/main/java/uk/org/whoami/authme/cache/auth/PlayerCache.java b/src/main/java/uk/org/whoami/authme/cache/auth/PlayerCache.java index ccba6ef29..34ca5a7c2 100644 --- a/src/main/java/uk/org/whoami/authme/cache/auth/PlayerCache.java +++ b/src/main/java/uk/org/whoami/authme/cache/auth/PlayerCache.java @@ -28,24 +28,24 @@ public class PlayerCache { } public void addPlayer(PlayerAuth auth) { - cache.put(auth.getNickname(), auth); + cache.put(auth.getNickname().toLowerCase(), auth); } public void updatePlayer(PlayerAuth auth) { - cache.remove(auth.getNickname()); - cache.put(auth.getNickname(), auth); + cache.remove(auth.getNickname().toLowerCase()); + cache.put(auth.getNickname().toLowerCase(), auth); } public void removePlayer(String user) { - cache.remove(user); + cache.remove(user.toLowerCase()); } public boolean isAuthenticated(String user) { - return cache.containsKey(user); + return cache.containsKey(user.toLowerCase()); } public PlayerAuth getAuth(String user) { - return cache.get(user); + return cache.get(user.toLowerCase()); } public static PlayerCache getInstance() { 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 a4acbc13e..17f63b115 100644 --- a/src/main/java/uk/org/whoami/authme/commands/AdminCommand.java +++ b/src/main/java/uk/org/whoami/authme/commands/AdminCommand.java @@ -176,7 +176,7 @@ public class AdminCommand implements CommandExecutor { if (!args[1].contains(".")) { final CommandSender fSender = sender; final String[] arguments = args; - Bukkit.getScheduler().runTask(plugin, new Runnable() { + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { PlayerAuth pAuth = null; @@ -219,7 +219,7 @@ public class AdminCommand implements CommandExecutor { } else { final CommandSender fSender = sender; final String[] arguments = args; - Bukkit.getScheduler().runTask(plugin, new Runnable() { + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { String message = "[AuthMe] "; @@ -344,12 +344,16 @@ public class AdminCommand implements CommandExecutor { bannedPlayers.add(off.getName().toLowerCase()); } final List bP = bannedPlayers; - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - database.purgeBanned(bP); - } - }); + if (database instanceof Thread) { + database.purgeBanned(bP); + } else { + Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { + @Override + public void run() { + database.purgeBanned(bP); + } + }); + } } else if (args[0].equalsIgnoreCase("spawn")) { try { if (sender instanceof Player) { diff --git a/src/main/java/uk/org/whoami/authme/commands/EmailCommand.java b/src/main/java/uk/org/whoami/authme/commands/EmailCommand.java index 84ca73da6..98b815872 100644 --- a/src/main/java/uk/org/whoami/authme/commands/EmailCommand.java +++ b/src/main/java/uk/org/whoami/authme/commands/EmailCommand.java @@ -172,13 +172,18 @@ public class EmailCommand implements CommandExecutor { } final String finalhashnew = hashnew; final PlayerAuth finalauth = auth; - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - finalauth.setHash(finalhashnew); - data.updatePassword(finalauth); - } - }); + if (data instanceof Thread) { + finalauth.setHash(hashnew); + data.updatePassword(auth); + } else { + Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { + @Override + public void run() { + finalauth.setHash(finalhashnew); + data.updatePassword(finalauth); + } + }); + } plugin.mail.main(auth, thePass); player.sendMessage(m._("email_send")); } catch (NoSuchAlgorithmException ex) { diff --git a/src/main/java/uk/org/whoami/authme/commands/UnregisterCommand.java b/src/main/java/uk/org/whoami/authme/commands/UnregisterCommand.java index eb61eb712..e2b2b9db3 100644 --- a/src/main/java/uk/org/whoami/authme/commands/UnregisterCommand.java +++ b/src/main/java/uk/org/whoami/authme/commands/UnregisterCommand.java @@ -100,7 +100,7 @@ public class UnregisterCommand implements CommandExecutor { BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name), delay); LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id.getTaskId()); } - sched.runTask(plugin, new MessageTask(plugin, name, m._("reg_msg"), interval)); + sched.scheduleSyncDelayedTask(plugin, new MessageTask(plugin, name, m._("reg_msg"), interval)); if(!Settings.unRegisteredGroup.isEmpty()){ Utils.getInstance().setGroup(player, Utils.groupType.UNREGISTERED); } 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 45d626deb..d0ed6d089 100644 --- a/src/main/java/uk/org/whoami/authme/datasource/MiniConnectionPoolManager.java +++ b/src/main/java/uk/org/whoami/authme/datasource/MiniConnectionPoolManager.java @@ -153,8 +153,8 @@ private synchronized Connection getConnection3() throws SQLException { else { pconn = dataSource.getPooledConnection(); pconn.addConnectionEventListener(poolConnectionEventListener); } - activeConnections++; Connection conn = pconn.getConnection(); + activeConnections++; assertInnerState(); return conn; } 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 c109b421e..4e89bb2fc 100644 --- a/src/main/java/uk/org/whoami/authme/datasource/MySQLDataSource.java +++ b/src/main/java/uk/org/whoami/authme/datasource/MySQLDataSource.java @@ -283,7 +283,7 @@ public class MySQLDataSource implements DataSource { } @Override - public boolean updateSession(PlayerAuth auth) { + public synchronized boolean updateSession(PlayerAuth auth) { Connection con = null; PreparedStatement pst = null; try { @@ -307,7 +307,7 @@ public class MySQLDataSource implements DataSource { } @Override - public int purgeDatabase(long until) { + public synchronized int purgeDatabase(long until) { Connection con = null; PreparedStatement pst = null; try { @@ -350,7 +350,7 @@ public class MySQLDataSource implements DataSource { } @Override - public boolean updateQuitLoc(PlayerAuth auth) { + public synchronized boolean updateQuitLoc(PlayerAuth auth) { Connection con = null; PreparedStatement pst = null; try { @@ -376,7 +376,7 @@ public class MySQLDataSource implements DataSource { } @Override - public int getIps(String ip) { + public synchronized int getIps(String ip) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; @@ -405,7 +405,7 @@ public class MySQLDataSource implements DataSource { } @Override - public boolean updateEmail(PlayerAuth auth) { + public synchronized boolean updateEmail(PlayerAuth auth) { Connection con = null; PreparedStatement pst = null; try { @@ -428,7 +428,7 @@ public class MySQLDataSource implements DataSource { } @Override - public boolean updateSalt(PlayerAuth auth) { + public synchronized boolean updateSalt(PlayerAuth auth) { if (columnSalt.isEmpty()) { return false; } @@ -497,7 +497,7 @@ public class MySQLDataSource implements DataSource { } @Override - public List getAllAuthsByName(PlayerAuth auth) { + public synchronized List getAllAuthsByName(PlayerAuth auth) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; @@ -526,7 +526,7 @@ public class MySQLDataSource implements DataSource { } @Override - public List getAllAuthsByIp(String ip) { + public synchronized List getAllAuthsByIp(String ip) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; @@ -555,7 +555,7 @@ public class MySQLDataSource implements DataSource { } @Override - public List getAllAuthsByEmail(String email) { + public synchronized List getAllAuthsByEmail(String email) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; @@ -584,7 +584,7 @@ public class MySQLDataSource implements DataSource { } @Override - public void purgeBanned(List banned) { + public synchronized void purgeBanned(List banned) { Connection con = null; PreparedStatement pst = null; try { 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 0f7aa99bb..afc5f8422 100644 --- a/src/main/java/uk/org/whoami/authme/datasource/SqliteDataSource.java +++ b/src/main/java/uk/org/whoami/authme/datasource/SqliteDataSource.java @@ -1,7 +1,3 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ package uk.org.whoami.authme.datasource; import java.sql.*; @@ -106,6 +102,7 @@ public class SqliteDataSource implements DataSource { + "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 + ";"); } 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 e83ba35e1..4bcbe14eb 100644 --- a/src/main/java/uk/org/whoami/authme/listener/AuthMePlayerListener.java +++ b/src/main/java/uk/org/whoami/authme/listener/AuthMePlayerListener.java @@ -170,7 +170,7 @@ public class AuthMePlayerListener implements Listener { } } } else { - Bukkit.getScheduler().runTask(plugin, new Runnable() + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -227,7 +227,7 @@ public class AuthMePlayerListener implements Listener { } } } else { - Bukkit.getScheduler().runTask(plugin, new Runnable() + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -285,7 +285,7 @@ public class AuthMePlayerListener implements Listener { } } } else { - Bukkit.getScheduler().runTask(plugin, new Runnable() + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -342,7 +342,7 @@ public class AuthMePlayerListener implements Listener { } } } else { - Bukkit.getScheduler().runTask(plugin, new Runnable() + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -399,7 +399,7 @@ public class AuthMePlayerListener implements Listener { } } } else { - Bukkit.getScheduler().runTask(plugin, new Runnable() + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -456,7 +456,7 @@ public class AuthMePlayerListener implements Listener { } } } else { - Bukkit.getScheduler().runTask(plugin, new Runnable() + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { @Override public void run() { @@ -827,16 +827,20 @@ public class AuthMePlayerListener implements Listener { return; } - if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead()) { + if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead()) { if(Settings.isSaveQuitLocationEnabled && data.isAuthAvailable(name)) { final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(),loc.getBlockX(),loc.getBlockY(),loc.getBlockZ(),loc.getWorld().getName()); try { - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - data.updateQuitLoc(auth); - } - }); + if (data instanceof Thread) { + data.updateQuitLoc(auth); + } else { + Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){ + @Override + public void run() { + data.updateQuitLoc(auth); + } + }); + } } catch (NullPointerException npe) { } } } @@ -898,12 +902,18 @@ public class AuthMePlayerListener implements Listener { if ((PlayerCache.getInstance().isAuthenticated(name)) && (!player.isDead()) && (Settings.isSaveQuitLocationEnabled.booleanValue()) && data.isAuthAvailable(name)) { final PlayerAuth auth = new PlayerAuth(event.getPlayer().getName().toLowerCase(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(),loc.getWorld().getName()); - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { - @Override - public void run() { - data.updateQuitLoc(auth); - } - }); + 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) { } } if (LimboCache.getInstance().hasLimboPlayer(name)) @@ -1181,12 +1191,18 @@ 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()); - Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){ - @Override - public void run() { - data.updateQuitLoc(auth); - } - }); + 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/plugin/manager/BungeeCordMessage.java b/src/main/java/uk/org/whoami/authme/plugin/manager/BungeeCordMessage.java index ae3bea3b3..27a37498a 100644 --- a/src/main/java/uk/org/whoami/authme/plugin/manager/BungeeCordMessage.java +++ b/src/main/java/uk/org/whoami/authme/plugin/manager/BungeeCordMessage.java @@ -8,7 +8,6 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; import uk.org.whoami.authme.AuthMe; -import uk.org.whoami.authme.ConsoleLogger; public class BungeeCordMessage implements PluginMessageListener { @@ -24,7 +23,6 @@ public class BungeeCordMessage implements PluginMessageListener { try { final DataInputStream in = new DataInputStream(new ByteArrayInputStream(message)); if (in.readUTF().equals("IP")) { //We need only the IP channel - ConsoleLogger.info("PluginMessage send to " + player.getName() + " , the message was : " + message.toString()); plugin.realIp.put(player.getName().toLowerCase(), in.readUTF()); //Put the IP (only the ip not the port) in the hashmap } } catch (IOException ex) { 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 111ff2a9f..f58d74c3f 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,8 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import uk.org.whoami.authme.AuthMe; +import uk.org.whoami.authme.security.pbkdf2.PBKDF2Engine; +import uk.org.whoami.authme.security.pbkdf2.PBKDF2Parameters; import uk.org.whoami.authme.settings.Settings; public class PasswordSecurity { @@ -105,6 +107,13 @@ public class PasswordSecurity { private static String getWBB3(String message, String salt) throws NoSuchAlgorithmException { return getSHA1(salt.concat(getSHA1(salt.concat(getSHA1(message))))); } + + 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); + PBKDF2Engine engine = new PBKDF2Engine(params); + return result + engine.deriveKey(password,57).toString(); + } private static String createSalt(int length) throws NoSuchAlgorithmException { byte[] msg = new byte[40]; @@ -226,6 +235,9 @@ public class PasswordSecurity { return getSHA512(password); case DOUBLEMD5: return getMD5(getMD5(password)); + case PBKDF2: + String saltpbkdf2 = createSalt(12); + return getPBKDF2(password, saltpbkdf2); default: throw new NoSuchAlgorithmException("Unknown hash algorithm"); } @@ -237,24 +249,24 @@ public class PasswordSecurity { return checkHash.phpbb_check_hash(password, hash); } if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.WBB3) { - String saltwbb3 = AuthMe.getInstance().database.getAuth(playername).getSalt(); - return hash.equals(getWBB3(password, saltwbb3)); + String salt = AuthMe.getInstance().database.getAuth(playername).getSalt(); + return hash.equals(getWBB3(password, salt)); } if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.IPB3) { - String saltipb = AuthMe.getInstance().database.getAuth(playername).getSalt(); - return hash.equals(getSaltedIPB3(password, saltipb)); + String salt = AuthMe.getInstance().database.getAuth(playername).getSalt(); + return hash.equals(getSaltedIPB3(password, salt)); } if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.BCRYPT) { - String saltbcrypt = AuthMe.getInstance().database.getAuth(playername).getSalt(); - return hash.equals(BCrypt.hashpw(password, saltbcrypt)); + String salt = AuthMe.getInstance().database.getAuth(playername).getSalt(); + return hash.equals(BCrypt.hashpw(password, salt)); } if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.PHPFUSION) { - String saltfusion = AuthMe.getInstance().database.getAuth(playername).getSalt(); - return hash.equals(getPhPFusion(password, saltfusion)); + String salt = AuthMe.getInstance().database.getAuth(playername).getSalt(); + return hash.equals(getPhPFusion(password, salt)); } if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.MYBB) { - String saltmybb = AuthMe.getInstance().database.getAuth(playername).getSalt(); - return hash.equals(getSaltedMyBB(password, saltmybb)); + String salt = AuthMe.getInstance().database.getAuth(playername).getSalt(); + return hash.equals(getSaltedMyBB(password, salt)); } if(Settings.getPasswordHash == HashAlgorithm.SMF) return hash.equals(getSHA1(playername.toLowerCase() + password)); @@ -265,15 +277,23 @@ public class PasswordSecurity { if(Settings.getPasswordHash == HashAlgorithm.DOUBLEMD5) return hash.equals(getMD5(getMD5(password))); if(!Settings.getMySQLColumnSalt.isEmpty() && Settings.getPasswordHash == HashAlgorithm.SALTED2MD5) { - String salt2md5 = AuthMe.getInstance().database.getAuth(playername).getSalt(); - return hash.equals(getMD5(getMD5(password) + salt2md5)); + String salt = AuthMe.getInstance().database.getAuth(playername).getSalt(); + return hash.equals(getMD5(getMD5(password) + salt)); } if(Settings.getPasswordHash == HashAlgorithm.JOOMLA) { - String saltj = hash.split(":")[1]; - return hash.equals(getMD5(password + saltj) + ":" + saltj); + String salt = hash.split(":")[1]; + return hash.equals(getMD5(password + salt) + ":" + salt); } if(Settings.getPasswordHash == HashAlgorithm.SHA512) return hash.equals(getSHA512(password)); + if(Settings.getPasswordHash == HashAlgorithm.PBKDF2) { + 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()); + PBKDF2Engine engine = new PBKDF2Engine(params); + return engine.verifyKey(password); + } // PlainText Password if(hash.length() < 32 ) return hash.equals(password); @@ -336,7 +356,7 @@ public class PasswordSecurity { public enum HashAlgorithm { MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB, PLAINTEXT, MYBB, IPB3, PHPFUSION, SMF, XFSHA1, - XFSHA256, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5 + XFSHA256, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5, PBKDF2 } } diff --git a/src/main/java/uk/org/whoami/authme/security/pbkdf2/BinTools.java b/src/main/java/uk/org/whoami/authme/security/pbkdf2/BinTools.java new file mode 100644 index 000000000..b3da28f69 --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/security/pbkdf2/BinTools.java @@ -0,0 +1,137 @@ +package uk.org.whoami.authme.security.pbkdf2; + +/** + *

+ * Free auxiliary functions. Copyright (c) 2007 Matthias Gärtner + *

+ *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + *

+ *

+ * This library 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 Lesser General Public License for more + * details. + *

+ *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

+ *

+ * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + *

+ * + * @author Matthias Gärtner + * @version 1.0 + */ +public class BinTools +{ + public static final String hex = "0123456789ABCDEF"; + + /** + * Simple binary-to-hexadecimal conversion. + * + * @param b + * Input bytes. May be null. + * @return Hexadecimal representation of b. Uppercase A-F, two characters + * per byte. Empty string on null input. + */ + public static String bin2hex(final byte[] b) + { + if (b == null) + { + return ""; + } + StringBuffer sb = new StringBuffer(2 * b.length); + for (int i = 0; i < b.length; i++) + { + int v = (256 + b[i]) % 256; + sb.append(hex.charAt((v / 16) & 15)); + sb.append(hex.charAt((v % 16) & 15)); + } + return sb.toString(); + } + + /** + * Convert hex string to array of bytes. + * + * @param s + * String containing hexadecimal digits. May be null. + * On odd length leading zero will be assumed. + * @return Array on bytes, non-null. + * @throws IllegalArgumentException + * when string contains non-hex character + */ + public static byte[] hex2bin(final String s) + { + String m = s; + if (s == null) + { + // Allow empty input string. + m = ""; + } + else if (s.length() % 2 != 0) + { + // Assume leading zero for odd string length + m = "0" + s; + } + byte r[] = new byte[m.length() / 2]; + for (int i = 0, n = 0; i < m.length(); n++) + { + char h = m.charAt(i++); + char l = m.charAt(i++); + r[n] = (byte) (hex2bin(h) * 16 + hex2bin(l)); + } + return r; + } + + /** + * Convert hex digit to numerical value. + * + * @param c + * 0-9, a-f, A-F allowd. + * @return 0-15 + * @throws IllegalArgumentException + * on non-hex character + */ + public static int hex2bin(char c) + { + if (c >= '0' && c <= '9') + { + return (c - '0'); + } + if (c >= 'A' && c <= 'F') + { + return (c - 'A' + 10); + } + if (c >= 'a' && c <= 'f') + { + return (c - 'a' + 10); + } + throw new IllegalArgumentException( + "Input string may only contain hex digits, but found '" + c + + "'"); + } + + public static void main(String[] args) + { + byte b[] = new byte[256]; + byte bb = 0; + for (int i = 0; i < 256; i++) + { + b[i] = bb++; + } + String s = bin2hex(b); + byte c[] = hex2bin(s); + String t = bin2hex(c); + if (!s.equals(t)) + { + throw new AssertionError("Mismatch"); + } + } +} diff --git a/src/main/java/uk/org/whoami/authme/security/pbkdf2/MacBasedPRF.java b/src/main/java/uk/org/whoami/authme/security/pbkdf2/MacBasedPRF.java new file mode 100644 index 000000000..a2cee8386 --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/security/pbkdf2/MacBasedPRF.java @@ -0,0 +1,111 @@ +package uk.org.whoami.authme.security.pbkdf2; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +/** + * Default PRF implementation based on standard javax.crypt.Mac mechanisms. + * + *
+ *

+ * A free Java implementation of Password Based Key Derivation Function 2 as + * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner + *

+ *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + *

+ *

+ * This library 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 Lesser General Public License for more + * details. + *

+ *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

+ *

+ * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + *

+ * + * @author Matthias Gärtner + * @version 1.0 + */ +public class MacBasedPRF implements PRF +{ + protected Mac mac; + + protected int hLen; + + protected String macAlgorithm; + + /** + * Create Mac-based Pseudo Random Function. + * + * @param macAlgorithm + * Mac algorithm to use, i.e. HMacSHA1 or HMacMD5. + */ + public MacBasedPRF(String macAlgorithm) + { + this.macAlgorithm = macAlgorithm; + try + { + mac = Mac.getInstance(macAlgorithm); + hLen = mac.getMacLength(); + } + catch (NoSuchAlgorithmException e) + { + throw new RuntimeException(e); + } + } + + public MacBasedPRF(String macAlgorithm, String provider) + { + this.macAlgorithm = macAlgorithm; + try + { + mac = Mac.getInstance(macAlgorithm, provider); + hLen = mac.getMacLength(); + } + catch (NoSuchAlgorithmException e) + { + throw new RuntimeException(e); + } + catch (NoSuchProviderException e) + { + throw new RuntimeException(e); + } + } + + public byte[] doFinal(byte[] M) + { + byte[] r = mac.doFinal(M); + return r; + } + + public int getHLen() + { + return hLen; + } + + public void init(byte[] P) + { + try + { + mac.init(new SecretKeySpec(P, macAlgorithm)); + } + catch (InvalidKeyException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2.java b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2.java new file mode 100644 index 000000000..6ac403808 --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2.java @@ -0,0 +1,98 @@ +package uk.org.whoami.authme.security.pbkdf2; + +/** + *

+ * A free Java implementation of Password Based Key Derivation Function 2 as + * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner + *

+ *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + *

+ *

+ * This library 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 Lesser General Public License for more + * details. + *

+ *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

+ *

+ * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + *

+ * + * @author Matthias Gärtner + * @version 1.0 + */ +public interface PBKDF2 +{ + /** + * Convert String-based input to internal byte array, then invoke PBKDF2. + * Desired key length defaults to Pseudo Random Function block size. + * + * @param inputPassword + * Candidate password to compute the derived key for. + * @return internal byte array + */ + public abstract byte[] deriveKey(String inputPassword); + + /** + * Convert String-based input to internal byte array, then invoke PBKDF2. + * + * @param inputPassword + * Candidate password to compute the derived key for. + * @param dkLen + * Specify desired key length + * @return internal byte array + */ + public abstract byte[] deriveKey(String inputPassword, int dkLen); + + /** + * Convert String-based input to internal byte arrays, then invoke PBKDF2 + * and verify result against the reference data that is supplied in the + * PBKDF2Parameters. + * + * @param inputPassword + * Candidate password to compute the derived key for. + * @return true password match; false + * incorrect password + */ + public abstract boolean verifyKey(String inputPassword); + + /** + * Allow reading of configured parameters. + * + * @return Currently set parameters. + */ + public abstract PBKDF2Parameters getParameters(); + + /** + * Allow setting of configured parameters. + * + * @param parameters + */ + public abstract void setParameters(PBKDF2Parameters parameters); + + /** + * Get currently set Pseudo Random Function. + * + * @return Currently set Pseudo Random Function + */ + public abstract PRF getPseudoRandomFunction(); + + /** + * Set the Pseudo Random Function to use. Note that deriveKeys/getPRF does + * init this object using the supplied candidate password. If this is + * undesired, one has to override getPRF. + * + * @param prf + * Pseudo Random Function to set. + */ + public abstract void setPseudoRandomFunction(PRF prf); +} diff --git a/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Engine.java b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Engine.java new file mode 100644 index 000000000..b2bc80ae4 --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Engine.java @@ -0,0 +1,401 @@ +package uk.org.whoami.authme.security.pbkdf2; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + *

+ * Request for Comments: 2898 PKCS #5: Password-Based Cryptography Specification + *

+ * Version 2.0 + * + *

+ * PBKDF2 (P, S, c, dkLen) + * + *

+ * Options: + *

    + *
  • PRF underlying pseudorandom function (hLen denotes the length in octets + * of the pseudorandom function output). PRF is pluggable.
  • + *
+ * + *

+ * Input: + *

    + *
  • P password, an octet string
  • + *
  • S salt, an octet string
  • + *
  • c iteration count, a positive integer
  • + *
  • dkLen intended length in octets of the derived key, a positive integer, + * at most (2^32 - 1) * hLen
  • + *
+ * + *

+ * Output: + *

    + *
  • DK derived key, a dkLen-octet string
  • + *
+ * + *
+ *

+ * A free Java implementation of Password Based Key Derivation Function 2 as + * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner + *

+ *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + *

+ *

+ * This library 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 Lesser General Public License for more + * details. + *

+ *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

+ *

+ * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + *

+ * + * @see RFC 2898 + * @author Matthias Gärtner + * @version 1.0 + */ +public class PBKDF2Engine implements PBKDF2 +{ + protected PBKDF2Parameters parameters; + + protected PRF prf; + + /** + * Constructor for PBKDF2 implementation object. PBKDF2 parameters must be + * passed later. + */ + public PBKDF2Engine() + { + this.parameters = null; + prf = null; + } + + /** + * Constructor for PBKDF2 implementation object. PBKDF2 parameters are + * passed so that this implementation knows iteration count, method to use + * and String encoding. + * + * @param parameters + * Data holder for iteration count, method to use et cetera. + */ + public PBKDF2Engine(PBKDF2Parameters parameters) + { + this.parameters = parameters; + prf = null; + } + + /** + * Constructor for PBKDF2 implementation object. PBKDF2 parameters are + * passed so that this implementation knows iteration count, method to use + * and String encoding. + * + * @param parameters + * Data holder for iteration count, method to use et cetera. + * @param prf + * Supply customer Pseudo Random Function. + */ + public PBKDF2Engine(PBKDF2Parameters parameters, PRF prf) + { + this.parameters = parameters; + this.prf = prf; + } + + public byte[] deriveKey(String inputPassword) + { + return deriveKey(inputPassword, 0); + } + + public byte[] deriveKey(String inputPassword, int dkLen) + { + byte[] r = null; + byte P[] = null; + String charset = parameters.getHashCharset(); + if (inputPassword == null) + { + inputPassword = ""; + } + try + { + if (charset == null) + { + P = inputPassword.getBytes(); + } + else + { + P = inputPassword.getBytes(charset); + } + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + assertPRF(P); + if (dkLen == 0) + { + dkLen = prf.getHLen(); + } + r = PBKDF2(prf, parameters.getSalt(), parameters.getIterationCount(), + dkLen); + return r; + } + + public boolean verifyKey(String inputPassword) + { + byte[] referenceKey = getParameters().getDerivedKey(); + if (referenceKey == null || referenceKey.length == 0) + { + return false; + } + byte[] inputKey = deriveKey(inputPassword, referenceKey.length); + + if (inputKey == null || inputKey.length != referenceKey.length) + { + return false; + } + for (int i = 0; i < inputKey.length; i++) + { + if (inputKey[i] != referenceKey[i]) + { + return false; + } + } + return true; + } + + /** + * Factory method. Default implementation is (H)MAC-based. To be overridden + * in derived classes. + * + * @param P + * User-supplied candidate password as array of bytes. + */ + protected void assertPRF(byte[] P) + { + if (prf == null) + { + prf = new MacBasedPRF(parameters.getHashAlgorithm()); + } + prf.init(P); + } + + public PRF getPseudoRandomFunction() + { + return prf; + } + + /** + * Core Password Based Key Derivation Function 2. + * + * @see RFC 2898 5.2 + * @param prf + * Pseudo Random Function (i.e. HmacSHA1) + * @param S + * Salt as array of bytes. null means no salt. + * @param c + * Iteration count (see RFC 2898 4.2) + * @param dkLen + * desired length of derived key. + * @return internal byte array + */ + protected byte[] PBKDF2(PRF prf, byte[] S, int c, int dkLen) + { + if (S == null) + { + S = new byte[0]; + } + int hLen = prf.getHLen(); + int l = ceil(dkLen, hLen); + int r = dkLen - (l - 1) * hLen; + byte T[] = new byte[l * hLen]; + int ti_offset = 0; + for (int i = 1; i <= l; i++) + { + _F(T, ti_offset, prf, S, c, i); + ti_offset += hLen; + } + if (r < hLen) + { + // Incomplete last block + byte DK[] = new byte[dkLen]; + System.arraycopy(T, 0, DK, 0, dkLen); + return DK; + } + return T; + } + + /** + * Integer division with ceiling function. + * + * @see RFC 2898 5.2 Step 2. + * @param a + * @param b + * @return ceil(a/b) + */ + protected int ceil(int a, int b) + { + int m = 0; + if (a % b > 0) + { + m = 1; + } + return a / b + m; + } + + /** + * Function F. + * + * @see RFC 2898 5.2 Step 3. + * @param dest + * Destination byte buffer + * @param offset + * Offset into destination byte buffer + * @param prf + * Pseudo Random Function + * @param S + * Salt as array of bytes + * @param c + * Iteration count + * @param blockIndex + */ + protected void _F(byte[] dest, int offset, PRF prf, byte[] S, int c, + int blockIndex) + { + int hLen = prf.getHLen(); + byte U_r[] = new byte[hLen]; + + // U0 = S || INT (i); + byte U_i[] = new byte[S.length + 4]; + System.arraycopy(S, 0, U_i, 0, S.length); + INT(U_i, S.length, blockIndex); + + for (int i = 0; i < c; i++) + { + U_i = prf.doFinal(U_i); + xor(U_r, U_i); + } + System.arraycopy(U_r, 0, dest, offset, hLen); + } + + /** + * Block-Xor. Xor source bytes into destination byte buffer. Destination + * buffer must be same length or less than source buffer. + * + * @param dest + * @param src + */ + protected void xor(byte[] dest, byte[] src) + { + for (int i = 0; i < dest.length; i++) + { + dest[i] ^= src[i]; + } + } + + /** + * Four-octet encoding of the integer i, most significant octet first. + * + * @see RFC 2898 5.2 Step 3. + * @param dest + * @param offset + * @param i + */ + protected void INT(byte[] dest, int offset, int i) + { + dest[offset + 0] = (byte) (i / (256 * 256 * 256)); + dest[offset + 1] = (byte) (i / (256 * 256)); + dest[offset + 2] = (byte) (i / (256)); + dest[offset + 3] = (byte) (i); + } + + public PBKDF2Parameters getParameters() + { + return parameters; + } + + public void setParameters(PBKDF2Parameters parameters) + { + this.parameters = parameters; + } + + public void setPseudoRandomFunction(PRF prf) + { + this.prf = prf; + } + + /** + * Convenience client function. Convert supplied password with random 8-byte + * salt and 1000 iterations using HMacSHA1. Assume that password is in + * ISO-8559-1 encoding. Output result as + * "Salt:iteration-count:PBKDF2" with binary data in hexadecimal + * encoding. + * + * Example: Password "password" (without the quotes) leads to + * 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04 + * + * @param args + * Supply the password as argument. + * @throws IOException + * @throws NoSuchAlgorithmException + */ + public static void main(String[] args) throws IOException, + NoSuchAlgorithmException + { + String password = "password"; + String candidate = null; + PBKDF2Formatter formatter = new PBKDF2HexFormatter(); + + if (args.length >= 1) + { + password = args[0]; + } + if (args.length >= 2) + { + candidate = args[1]; + } + if (candidate == null) + { + // Creation mode + SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); + byte[] salt = new byte[8]; + sr.nextBytes(salt); + int iterations = 1000; + PBKDF2Parameters p = new PBKDF2Parameters("HmacSHA1", "ISO-8859-1", + salt, iterations); + PBKDF2Engine e = new PBKDF2Engine(p); + p.setDerivedKey(e.deriveKey(password)); + candidate = formatter.toString(p); + System.out.println(candidate); + } + else + { + // Verification mode + PBKDF2Parameters p = new PBKDF2Parameters(); + p.setHashAlgorithm("HmacSHA1"); + p.setHashCharset("ISO-8859-1"); + if (formatter.fromString(p, candidate)) + { + throw new IllegalArgumentException( + "Candidate data does not have correct format (\"" + + candidate + "\")"); + } + PBKDF2Engine e = new PBKDF2Engine(p); + boolean verifyOK = e.verifyKey(password); + System.out.println(verifyOK ? "OK" : "FAIL"); + System.exit(verifyOK ? 0 : 1); + } + } +} diff --git a/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Formatter.java b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Formatter.java new file mode 100644 index 000000000..678bb6b92 --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Formatter.java @@ -0,0 +1,54 @@ +package uk.org.whoami.authme.security.pbkdf2; + +/** + *

+ * A free Java implementation of Password Based Key Derivation Function 2 as + * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner + *

+ *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + *

+ *

+ * This library 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 Lesser General Public License for more + * details. + *

+ *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

+ *

+ * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + *

+ * + * @author Matthias Gärtner + * @version 1.0 + */ +public interface PBKDF2Formatter +{ + /** + * Convert parameters to String. + * + * @param p + * Parameters object to output. + * @return String representation + */ + public abstract String toString(PBKDF2Parameters p); + + /** + * Convert String to parameters. Depending on actual implementation, it may + * be required to set further fields externally. + * + * @param s + * String representation of parameters to decode. + * @return false syntax OK, true some syntax + * issue. + */ + public abstract boolean fromString(PBKDF2Parameters p, String s); +} diff --git a/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2HexFormatter.java b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2HexFormatter.java new file mode 100644 index 000000000..b4b2f46d1 --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2HexFormatter.java @@ -0,0 +1,65 @@ +package uk.org.whoami.authme.security.pbkdf2; + +/** + *

+ * A free Java implementation of Password Based Key Derivation Function 2 as + * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner + *

+ *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + *

+ *

+ * This library 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 Lesser General Public License for more + * details. + *

+ *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

+ *

+ * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + *

+ * + * @author Matthias Gärtner + * @version 1.0 + */ +public class PBKDF2HexFormatter implements PBKDF2Formatter +{ + public boolean fromString(PBKDF2Parameters p, String s) + { + if (p == null || s == null) + { + return true; + } + + String[] p123 = s.split(":"); + if (p123 == null || p123.length != 3) + { + return true; + } + + byte salt[] = BinTools.hex2bin(p123[0]); + int iterationCount = Integer.parseInt(p123[1]); + byte bDK[] = BinTools.hex2bin(p123[2]); + + p.setSalt(salt); + p.setIterationCount(iterationCount); + p.setDerivedKey(bDK); + return false; + } + + public String toString(PBKDF2Parameters p) + { + String s = BinTools.bin2hex(p.getSalt()) + ":" + + String.valueOf(p.getIterationCount()) + ":" + + BinTools.bin2hex(p.getDerivedKey()); + return s; + } +} diff --git a/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Parameters.java b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Parameters.java new file mode 100644 index 000000000..6732b1dde --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PBKDF2Parameters.java @@ -0,0 +1,165 @@ +package uk.org.whoami.authme.security.pbkdf2; + +/** + *

+ * Parameter data holder for PBKDF2 configuration. + *

+ * + *
+ *

+ * A free Java implementation of Password Based Key Derivation Function 2 as + * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner + *

+ *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + *

+ *

+ * This library 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 Lesser General Public License for more + * details. + *

+ *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

+ *

+ * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + *

+ * + * @author Matthias Gärtner + * @version 1.0 + */ +public class PBKDF2Parameters +{ + protected byte[] salt; + + protected int iterationCount; + + protected String hashAlgorithm; + + protected String hashCharset; + + /** + * The derived key is actually only a convenience to store a reference + * derived key. It is not used during computation. + */ + protected byte[] derivedKey; + + /** + * Constructor. Defaults to null for byte arrays, UTF-8 as + * character set and 1000 for iteration count. + * + */ + public PBKDF2Parameters() + { + this.hashAlgorithm = null; + this.hashCharset = "UTF-8"; + this.salt = null; + this.iterationCount = 1000; + this.derivedKey = null; + } + + /** + * Constructor. + * + * @param hashAlgorithm + * for example HMacSHA1 or HMacMD5 + * @param hashCharset + * for example UTF-8 + * @param salt + * Salt as byte array, may be null (not + * recommended) + * @param iterationCount + * Number of iterations to execute. Recommended value 1000. + */ + public PBKDF2Parameters(String hashAlgorithm, String hashCharset, + byte[] salt, int iterationCount) + { + this.hashAlgorithm = hashAlgorithm; + this.hashCharset = hashCharset; + this.salt = salt; + this.iterationCount = iterationCount; + this.derivedKey = null; + } + + /** + * Constructor. + * + * @param hashAlgorithm + * for example HMacSHA1 or HMacMD5 + * @param hashCharset + * for example UTF-8 + * @param salt + * Salt as byte array, may be null (not + * recommended) + * @param iterationCount + * Number of iterations to execute. Recommended value 1000. + * @param derivedKey + * Convenience data holder, not used during computation. + */ + public PBKDF2Parameters(String hashAlgorithm, String hashCharset, + byte[] salt, int iterationCount, byte[] derivedKey) + { + this.hashAlgorithm = hashAlgorithm; + this.hashCharset = hashCharset; + this.salt = salt; + this.iterationCount = iterationCount; + this.derivedKey = derivedKey; + } + + public int getIterationCount() + { + return iterationCount; + } + + public void setIterationCount(int iterationCount) + { + this.iterationCount = iterationCount; + } + + public byte[] getSalt() + { + return salt; + } + + public void setSalt(byte[] salt) + { + this.salt = salt; + } + + public byte[] getDerivedKey() + { + return derivedKey; + } + + public void setDerivedKey(byte[] derivedKey) + { + this.derivedKey = derivedKey; + } + + public String getHashAlgorithm() + { + return hashAlgorithm; + } + + public void setHashAlgorithm(String hashAlgorithm) + { + this.hashAlgorithm = hashAlgorithm; + } + + public String getHashCharset() + { + return hashCharset; + } + + public void setHashCharset(String hashCharset) + { + this.hashCharset = hashCharset; + } +} diff --git a/src/main/java/uk/org/whoami/authme/security/pbkdf2/PRF.java b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PRF.java new file mode 100644 index 000000000..a7ab142b4 --- /dev/null +++ b/src/main/java/uk/org/whoami/authme/security/pbkdf2/PRF.java @@ -0,0 +1,60 @@ +package uk.org.whoami.authme.security.pbkdf2; + +/** + *

+ * A free Java implementation of Password Based Key Derivation Function 2 as + * defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner + *

+ *

+ * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + *

+ *

+ * This library 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 Lesser General Public License for more + * details. + *

+ *

+ * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *

+ *

+ * For Details, see http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. + *

+ * + * @author Matthias Gärtner + * @version 1.0 + */ +public interface PRF +{ + /** + * Initialize this instance with the user-supplied password. + * + * @param P + * The password supplied as array of bytes. It is the caller's + * task to convert String passwords to bytes as appropriate. + */ + public void init(byte[] P); + + /** + * Pseudo Random Function + * + * @param M + * Input data/message etc. Together with any data supplied during + * initilization. + * @return Random bytes of hLen length. + */ + public byte[] doFinal(byte[] M); + + /** + * Query block size of underlying algorithm/mechanism. + * + * @return block size + */ + public int getHLen(); +} 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 524eed949..c1bdf497d 100644 --- a/src/main/java/uk/org/whoami/authme/threads/MySQLThread.java +++ b/src/main/java/uk/org/whoami/authme/threads/MySQLThread.java @@ -299,7 +299,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public boolean updateSession(PlayerAuth auth) { + public synchronized boolean updateSession(PlayerAuth auth) { Connection con = null; PreparedStatement pst = null; try { @@ -323,7 +323,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public int purgeDatabase(long until) { + public synchronized int purgeDatabase(long until) { Connection con = null; PreparedStatement pst = null; try { @@ -366,7 +366,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public boolean updateQuitLoc(PlayerAuth auth) { + public synchronized boolean updateQuitLoc(PlayerAuth auth) { Connection con = null; PreparedStatement pst = null; try { @@ -392,7 +392,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public int getIps(String ip) { + public synchronized int getIps(String ip) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; @@ -421,7 +421,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public boolean updateEmail(PlayerAuth auth) { + public synchronized boolean updateEmail(PlayerAuth auth) { Connection con = null; PreparedStatement pst = null; try { @@ -444,7 +444,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public boolean updateSalt(PlayerAuth auth) { + public synchronized boolean updateSalt(PlayerAuth auth) { if (columnSalt.isEmpty()) { return false; } @@ -513,7 +513,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public List getAllAuthsByName(PlayerAuth auth) { + public synchronized List getAllAuthsByName(PlayerAuth auth) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; @@ -542,7 +542,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public List getAllAuthsByIp(String ip) { + public synchronized List getAllAuthsByIp(String ip) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; @@ -571,7 +571,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public List getAllAuthsByEmail(String email) { + public synchronized List getAllAuthsByEmail(String email) { Connection con = null; PreparedStatement pst = null; ResultSet rs = null; @@ -600,7 +600,7 @@ public class MySQLThread extends Thread implements DataSource { } @Override - public void purgeBanned(List banned) { + public synchronized void purgeBanned(List banned) { Connection con = null; PreparedStatement pst = null; try { @@ -617,4 +617,35 @@ public class MySQLThread extends Thread implements DataSource { close(con); } } + +/* public synchronized boolean makeSureConnectionIsReady() { + try { + conPool.getValidConnection(); + return true; + } catch (TimeoutException te) { + try { + reconnect(); + } catch (TimeoutException e) { + return false; + } catch (ClassNotFoundException e) { + return false; + } catch (SQLException e) { + return false; + } + return true; + } + } + + 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("Connection pool reconnected"); + } */ } diff --git a/src/main/java/uk/org/whoami/authme/threads/SQLiteThread.java b/src/main/java/uk/org/whoami/authme/threads/SQLiteThread.java index 48f11e6a0..b1c82ef35 100644 --- a/src/main/java/uk/org/whoami/authme/threads/SQLiteThread.java +++ b/src/main/java/uk/org/whoami/authme/threads/SQLiteThread.java @@ -123,6 +123,7 @@ public class SQLiteThread extends Thread implements DataSource { + "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 + ";"); } diff --git a/src/main/resources/messages_br.yml b/src/main/resources/messages_br.yml index 35c8b11db..de44144d5 100644 --- a/src/main/resources/messages_br.yml +++ b/src/main/resources/messages_br.yml @@ -15,7 +15,7 @@ no_perm: '&cSem permissao!' error: '&fOcorreu um erro de sistema, por favor reporte ao ADM.' login_msg: '&cPara entrar digite: "/login password"' reg_msg: '&cPara registrar um nick digite: "/register senha senha"' -reg_email_msg: '&cPlease register with "/register "' +reg_email_msg: '&cPara registrar um nick digite: "/register "' usage_unreg: '&cPara desregistrar digite: /unregister senha' pwd_changed: '&cSenha modificada!' user_unknown: '&cNome de usuario nao existe. Verifique.' @@ -29,23 +29,23 @@ registered: '&cRegistrado com sucesso!' pass_len: '&fSenha muito curta.' reload: '&fAuthMe Recarregado.' timeout: '&fDemorou....' -name_len: '&cYour nickname is too Short or too long' -regex: '&cYour nickname contains illegal characters. Allowed chars: REG_EX' -add_email: '&cPlease add your email with : /email add yourEmail confirmEmail' -bad_database_email: '[AuthMe] This /email command only available with MySQL and SQLite, contact an Admin' -recovery_email: '&cForgot your password? Please use /email recovery ' -usage_captcha: '&cUsage: /captcha ' -wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA' -valid_captcha: '&cYour captcha is valid !' -kick_forvip: '&cA VIP Player join the full server!' +name_len: '&cSeu nome de usuário é muito longo' +regex: '&cSeu nome de usuário tem caracteres ilegais. Permitido: REG_EX' +add_email: '&cAdicione seu e-mail, digite: /email add e-mail e-mail' +bad_database_email: '[AuthMe] Comando /email disponibilizado apenas com MySQL e SQLite, contate um Admin' +recovery_email: '&cEsqueceu sua senha? Digite /email recovery ' +usage_captcha: '&cDigite: /captcha ' +wrong_captcha: '&Captcha errado, digite: /captcha THE_CAPTCHA' +valid_captcha: '&cSeu captcha é válido!' +kick_forvip: '&cUsuário VIP entrou no servidor cheio!' 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 +usage_email_add: '&fDigite: /email add ' +usage_email_change: '&fDigite: /email change ' +usage_email_recovery: '&fDigite: /email recovery ' +new_email_invalid: '[AuthMe] Novo e-mail inválido!' +old_email_invalid: '[AuthMe] E-mail anterior, inválido!' +email_invalid: '[AuthMe] E-mail iválido' +email_added: '[AuthMe] E-mail adicionado com sucesso!' +email_confirm: '[AuthMe] Confirme seu e-mail!' +email_changed: '[AuthMe] E-mail alterado!' +email_send: '[AuthMe] E-mail com nova senha enviado!' diff --git a/src/main/resources/messages_cz.yml b/src/main/resources/messages_cz.yml index b8626ce8c..005e15ab0 100644 --- a/src/main/resources/messages_cz.yml +++ b/src/main/resources/messages_cz.yml @@ -41,8 +41,8 @@ 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 ' +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!' diff --git a/src/main/resources/messages_de.yml b/src/main/resources/messages_de.yml index 380b05859..ec5bb83f8 100644 --- a/src/main/resources/messages_de.yml +++ b/src/main/resources/messages_de.yml @@ -41,8 +41,8 @@ wrong_captcha: '&cFalsches Captcha, bitte nutze: /captcha ' valid_captcha: '&cDas Captcha ist korrekt!' kick_forvip: '&cEin VIP Spieler hat den vollen Server betreten!' kick_fullserver: '&cDer Server ist momentan voll, Sorry!' -usage_email_add: '&fUsage: /email add ' -usage_email_change: '&fUsage: /email change ' +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!' diff --git a/src/main/resources/messages_en.yml b/src/main/resources/messages_en.yml index 59d598b44..7255965d0 100644 --- a/src/main/resources/messages_en.yml +++ b/src/main/resources/messages_en.yml @@ -41,8 +41,8 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA' valid_captcha: '&cYour captcha is valid !' 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_add: '&fUsage: /email add ' +usage_email_change: '&fUsage: /email change oldEmail> ' usage_email_recovery: '&fUsage: /email recovery ' new_email_invalid: '[AuthMe] New email invalid!' old_email_invalid: '[AuthMe] Old email invalid!' diff --git a/src/main/resources/messages_es.yml b/src/main/resources/messages_es.yml index 85b5a44a1..39aa32e47 100644 --- a/src/main/resources/messages_es.yml +++ b/src/main/resources/messages_es.yml @@ -42,8 +42,8 @@ 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_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!' diff --git a/src/main/resources/messages_fi.yml b/src/main/resources/messages_fi.yml index 284978880..0e0d8a0aa 100644 --- a/src/main/resources/messages_fi.yml +++ b/src/main/resources/messages_fi.yml @@ -41,8 +41,8 @@ wrong_captcha: '&cVäärä varmistus, käytä : /captcha THE_CAPTCHA' valid_captcha: '&cSinun varmistus epäonnistui.!' 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_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!' diff --git a/src/main/resources/messages_hu.yml b/src/main/resources/messages_hu.yml index 4ab51fa94..e5d9454bc 100644 --- a/src/main/resources/messages_hu.yml +++ b/src/main/resources/messages_hu.yml @@ -41,8 +41,8 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA' valid_captcha: '&cYour captcha is valid !' 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_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!' diff --git a/src/main/resources/messages_it.yml b/src/main/resources/messages_it.yml index a6747d873..e578811d4 100644 --- a/src/main/resources/messages_it.yml +++ b/src/main/resources/messages_it.yml @@ -41,13 +41,13 @@ wrong_captcha: '&cCaptcha sbagliato, perfavore fai: /captcha THE_CAPTCHA' valid_captcha: "&cIl tuo captcha è valido!" kick_forvip: "&cUn player VIP è entrato mentre il server era pieno!" kick_fullserver: "&cIl server è attualmente pieno, ci dispiace!" -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 +usage_email_add: '&fUtilizzo: /email add ' +usage_email_change: '&fUtilizzo: /email change ' +usage_email_recovery: '&fUtilizzo: /email recovery ' +new_email_invalid: '[AuthMe] La nuova email non è valida!' +old_email_invalid: '[AuthMe] La vecchia email non è valida!' +email_invalid: "[AuthMe] L'email non è valida" +email_added: '[AuthMe] Email Aggiunta!' +email_confirm: '[AuthMe] Conferma la tua Email!' +email_changed: '[AuthMe] Email cambiata!' +email_send: '[AuthMe] Email di recupero inviata!' diff --git a/src/main/resources/messages_ko.yml b/src/main/resources/messages_ko.yml index 6fb56a487..fd65f870d 100644 --- a/src/main/resources/messages_ko.yml +++ b/src/main/resources/messages_ko.yml @@ -1,53 +1,53 @@ -unknown_user: 사용자는 데이터베이스에 없습니다 -unsafe_spawn: 당신이 나갔던 위치는 안전하지 않았습니다, 당신을 윌드 스폰으로 텔레포트시킵니다 -not_logged_in: '&c로그인하지 않았습니다!' -reg_voluntarily: 당신이 서버에 게정을 등록하고 싶다면 "/register 비밀번호 비밀번호재입력"을 치세요 -usage_log: '&c사용법: /login 비밀번호' -wrong_pwd: '&c잘못된 비밀번호입니다' -unregistered: '&c성공적으로 회원탈퇴되었습니다!' -reg_disabled: '&c회원가입이 성공적으로 비활성화되었습니다' -valid_session: '&c세션 로그인' -login: '&c성공적으로 로그인 되었습니다!' -vb_nonActiv: 당신의 계정은 활성화되어 있지 않습니다 당신의 이메일을 체크해주세요! -user_regged: '&c사용자 이름은 이미 등록되어 있습니다' -usage_reg: '&c사용법: /register 비밀번호 비밀번호재입력' -max_reg: 당신은 가입할 수 있는 계정의 최대 한도 수를 넘었습니다 -no_perm: '&c권한이 없습니다' -error: 오류가 발생했습니다; 관리자한테 문의하세요 -login_msg: '&c로그인 하실려면 "/login 비밀번호"를 치세요' -reg_msg: '&c가입하실려면 "/register 비밀번호 비밀번호재입력"을 치세요' -reg_email_msg: '&c가입하실려면 "/register <이메일> <이메일재입력>을 치세요"' -usage_unreg: '&c사용법: /unregister 비밀번호' -pwd_changed: '&c비밀번호가 변경되었습니다!' -user_unknown: '&c사용자 이름은 등록되지 않았습니다' -password_error: 비밀번호가 일치하지 않습니다 -unvalid_session: Session Dataes doesnt corrispond 세션이 끝날때 까지 기달려주세요 -reg_only: 회원가입은 플레이어만 할 수 있습니다! http://example.com 에 가입해주세요 -logged_in: '&c이미 로그인되어 있습니다!' -logout: '&c성공적으로 로그아웃되었습니다' -same_nick: 같은 닉네임이 이미 게임중입니다 -registered: '&c성공적으로 회원가입되었습니다!' -pass_len: 당신의 비밀번호는 최소 글자나 최대글자를 초과하였습니다 적당한 비밀번호 글자로 해주세요 -reload: 설정과 데이터베이스가 리로드되었습니다 -timeout: 로그인 시간 초과 -usage_changepassword: '사용법: /changepassword 기존비밀번호 새비밀번호' -name_len: '&c당신의 닉네임은 너무 길거나 짧습니다' -regex: '&c당신의 닉네임에 잘못된 문자가 포함되어 있습니다. 허용된 글자: REG_EX' -add_email: '&c당신의 이메일을 : /email add yourEmail confirmEmail 명령어로 추가해주세요' -bad_database_email: '[AuthMe] /email 명령어는 오직 MySQL 와 SQLite에서만 가능합니다, 관리자에게 문의해보세요' -recovery_email: '&c비밀번호를 잊어버리셨다고요? /email recovery <자신의이메일>을 사용해서 복구해보세요' -usage_captcha: '&c사용법: /captcha <캡차>' -wrong_captcha: '&c잘못된 캡차입니다, 올바른 사용법 : /captcha THE_CAPTCHA' -valid_captcha: '&c당신의 캡차는 올바릅니다 !' -kick_forvip: '&c한 VIP 플레이어가 만원인 서버에 입장했습니다!!' -kick_fullserver: '&c그 서버는 실제로 만원입니다, 미안!' -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 !' +unknown_user: 사용자는 데이터베이스에 없습니다 +unsafe_spawn: 당신이 나갔던 위치는 안전하지 않았습니다, 당신을 윌드 스폰으로 텔레포트시킵니다 +not_logged_in: '&c로그인하지 않았습니다!' +reg_voluntarily: 당신이 서버에 게정을 등록하고 싶다면 "/register 비밀번호 비밀번호재입력"을 치세요 +usage_log: '&c사용법: /login 비밀번호' +wrong_pwd: '&c잘못된 비밀번호입니다' +unregistered: '&c성공적으로 회원탈퇴되었습니다!' +reg_disabled: '&c회원가입이 성공적으로 비활성화되었습니다' +valid_session: '&c세션 로그인' +login: '&c성공적으로 로그인 되었습니다!' +vb_nonActiv: 당신의 계정은 활성화되어 있지 않습니다 당신의 이메일을 체크해주세요! +user_regged: '&c사용자 이름은 이미 등록되어 있습니다' +usage_reg: '&c사용법: /register 비밀번호 비밀번호재입력' +max_reg: 당신은 가입할 수 있는 계정의 최대 한도 수를 넘었습니다 +no_perm: '&c권한이 없습니다' +error: 오류가 발생했습니다; 관리자한테 문의하세요 +login_msg: '&c로그인 하실려면 "/login 비밀번호"를 치세요' +reg_msg: '&c가입하실려면 "/register 비밀번호 비밀번호재입력"을 치세요' +reg_email_msg: '&c가입하실려면 "/register <이메일> <이메일재입력>을 치세요"' +usage_unreg: '&c사용법: /unregister 비밀번호' +pwd_changed: '&c비밀번호가 변경되었습니다!' +user_unknown: '&c사용자 이름은 등록되지 않았습니다' +password_error: 비밀번호가 일치하지 않습니다 +unvalid_session: 세션 데이터베이스가 일치하지 않습니다 세션이 끝날때 까지 기달려주세요 +reg_only: 회원가입은 플레이어만 할 수 있습니다! http://example.com 에 가입해주세요 +logged_in: '&c이미 로그인되어 있습니다!' +logout: '&c성공적으로 로그아웃되었습니다' +same_nick: 같은 닉네임이 이미 게임중입니다 +registered: '&c성공적으로 회원가입되었습니다!' +pass_len: 당신의 비밀번호는 최소 글자나 최대글자를 초과하였습니다 적당한 비밀번호 글자로 해주세요 +reload: 설정과 데이터베이스가 리로드되었습니다 +timeout: 로그인 시간 초과 +usage_changepassword: '사용법: /changepassword 기존비밀번호 새비밀번호' +name_len: '&c당신의 닉네임은 너무 길거나 짧습니다' +regex: '&c당신의 닉네임에 잘못된 문자가 포함되어 있습니다. 허용된 글자: REG_EX' +add_email: '&c당신의 이메일을 : /email add yourEmail confirmEmail 명령어로 추가해주세요' +bad_database_email: '[AuthMe] /email 명령어는 오직 MySQL 와 SQLite에서만 가능합니다, 관리자에게 문의해보세요' +recovery_email: '&c비밀번호를 잊어버리셨다고요? /email recovery <자신의이메일>을 사용해서 복구해보세요' +usage_captcha: '&c사용법: /captcha <캡차>' +wrong_captcha: '&c잘못된 캡차입니다, 올바른 사용법 : /captcha THE_CAPTCHA' +valid_captcha: '&c당신의 캡차는 올바릅니다 !' +kick_forvip: '&c한 VIP 플레이어가 만원인 서버에 입장했습니다!!' +kick_fullserver: '&c그 서버는 실제로 만원입니다, 미안!' +usage_email_add: '&f사용법: /email add <이메일> <이메일재입력> ' +usage_email_change: '&f사용법: /email change ' +usage_email_recovery: '&f사용법: /email recovery <이메일>' +new_email_invalid: '[AuthMe] 새 이메일이 잘못되었습니다!' +old_email_invalid: '[AuthMe] 기존 이메일이 잘못되었습니다!' +email_invalid: '[AuthMe] 이메일이 잘못되었습니다' +email_added: '[AuthMe] 이메일 추가됨 !' +email_confirm: '[AuthMe] 이메일을 확인해주세요 !' +email_changed: '[AuthMe] 이메일 변경됨 !' +email_send: '[AuthMe] 복구 이메일 발송됨 !' diff --git a/src/main/resources/messages_lt.yml b/src/main/resources/messages_lt.yml index 734ff07ce..333275880 100644 --- a/src/main/resources/messages_lt.yml +++ b/src/main/resources/messages_lt.yml @@ -41,9 +41,9 @@ wrong_captcha: '&cNeteisinga Captcha, naudokite : /captcha THE_CAPTCHA' valid_captcha: '&cJusu captcha Teisinga!' kick_forvip: '&cA VIP prisijunge i pilna serveri!' kick_fullserver: '&cServeris yra pilnas, Atsiprasome.' -usage_email_add: '&fUsage: /email add ' -usage_email_change: '&fUsage: /email change ' -usage_email_recovery: '&fUsage: /email recovery ' +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' diff --git a/src/main/resources/messages_pl.yml b/src/main/resources/messages_pl.yml index fb081accc..a02975675 100644 --- a/src/main/resources/messages_pl.yml +++ b/src/main/resources/messages_pl.yml @@ -41,9 +41,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA' valid_captcha: '&cYour captcha is valid !' 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 ' +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' diff --git a/src/main/resources/messages_pt.yml b/src/main/resources/messages_pt.yml index beacb9657..91e5cd369 100644 --- a/src/main/resources/messages_pt.yml +++ b/src/main/resources/messages_pt.yml @@ -15,7 +15,7 @@ max_reg: '&cAtingiu o numero máximo de registos permitidos' no_perm: '&cSem Permissões' error: '&fOcorreu um erro; Por favor contacte um admin' login_msg: '&cIdentifique-se com "/login password"' -reg_msg: '&cPor favor registe-se com "/register password ConfirmePassword"' +reg_msg: '&cPor favor registe-se com "/register password confirmePassword"' reg_email_msg: '&ePor favor registe-se com "/register "' usage_unreg: '&cUse: /unregister password' pwd_changed: '&cPassword alterada!' @@ -37,14 +37,14 @@ add_email: '&cPor favor adicione o seu email com : /email add seuEmail confirmar bad_database_email: '[AuthMe] O comando /email não está disponível contacte o staff via ticket' recovery_email: '&cPerdeu a sua password? Para a recuperar escreva /email recovery ' usage_captcha: '&cUse: /captcha ' -wrong_captcha: '&cCaptcha errado, por favor use : /captcha THE_CAPTCHA' +wrong_captcha: '&cCaptcha errado, por favor use: /captcha THE_CAPTCHA' valid_captcha: '&cO seu captcha é válido!' kick_forvip: '&cUm jogador VIP entrou no servidor cheio!' kick_fullserver: '&cO servidor está actualmente cheio, lamentamos!' -usage_email_add: '&fUse: /email add ' +usage_email_add: '&fUse: /email add ' usage_email_change: '&fUse: /email change ' -usage_email_recovery: '&fUse: /email recovery ' -email_add: '/email add ' +usage_email_recovery: '&fUse: /email recovery ' +email_add: '/email add ' new_email_invalid: 'Novo email inválido!' old_email_invalid: 'Email antigo inválido!' email_invalid: 'Email inválido!' diff --git a/src/main/resources/messages_ru.yml b/src/main/resources/messages_ru.yml index 78d6cefb1..268d961b0 100644 --- a/src/main/resources/messages_ru.yml +++ b/src/main/resources/messages_ru.yml @@ -46,9 +46,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA' valid_captcha: '&cYour captcha is valid !' 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 ' +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' diff --git a/src/main/resources/messages_sk.yml b/src/main/resources/messages_sk.yml index ce2018382..6626b781a 100644 --- a/src/main/resources/messages_sk.yml +++ b/src/main/resources/messages_sk.yml @@ -10,7 +10,7 @@ usage_reg: '&cPríkaz: /register heslo zopakujHeslo' usage_log: '&cPríkaz: /login heslo' user_unknown: '&cZadané meno nie je zaregistrované!' pwd_changed: '&cHeslo zmenené!' -reg_only: '&fVstup iba pre registrovanych! Navstiv http://www.cs-gaming.eu pre registráciu' +reg_only: '&fVstup iba pre registrovanych! Navstiv http://example.com pre registráciu' valid_session: '&cZapamätané prihlásenie' login_msg: '&cPrihlás sa príkazom "/login heslo"' reg_msg: '&cZaregistruj sa príkazom "/register heslo zopakujHeslo"' @@ -45,9 +45,9 @@ wrong_captcha: '&cWrong Captcha, please use : /captcha THE_CAPTCHA' valid_captcha: '&cYour captcha is valid !' 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 ' +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' diff --git a/src/main/resources/messages_zhcn.yml b/src/main/resources/messages_zhcn.yml index 6cc2f81d0..117c415f2 100644 --- a/src/main/resources/messages_zhcn.yml +++ b/src/main/resources/messages_zhcn.yml @@ -41,9 +41,9 @@ wrong_captcha: '&c错误的验证码,请输入:“/captcha <验证码>”' valid_captcha: '&c你的验证码是有效的!' 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 ' +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' diff --git a/src/main/resources/messages_zhtw.yml b/src/main/resources/messages_zhtw.yml index c83dbb761..e333f050e 100644 --- a/src/main/resources/messages_zhtw.yml +++ b/src/main/resources/messages_zhtw.yml @@ -22,7 +22,7 @@ pwd_changed: '&c你成功的更換了你的密碼 !' user_unknown: '&c此用戶名沒有已登記資料 。' password_error: '&f密碼不符合 。' unvalid_session: '&f登入階段資料已損壞 , 請等待登入階段結束 。' -reg_only: '&f限已註冊會員 , 請先到 http://member.usociety.org 註冊 。' +reg_only: '&f限已註冊會員 , 請先到 http://example.com 註冊 。' logged_in: '&c你已經登入過了 。' logout: '&b你成功的登出了 。' same_nick: '&f同名玩家已在遊玩 。' @@ -41,9 +41,9 @@ wrong_captcha: '&c你輸入了錯誤的驗證碼,請使用 《 /captcha <驗 valid_captcha: '&c你的驗證碼是無效的 !' 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 ' +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' diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 33afb27db..37882aa7d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,7 +3,7 @@ author: Xephi59 website: http://www.multiplayer-italia.com/ 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.2 +version: 2.9.3 softdepend: [Vault, ChestShop, Spout, Multiverse-Core, Notifications, Citizens, CombatTag, Essentials, EssentialsSpawn] commands: register: