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: