diff --git a/.gitignore b/.gitignore
index 850a8a4..d0367bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/.settings
+/lib
/bin
/target
/.classpath
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..773b5b7
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,100 @@
+
+ 4.0.0
+ com.cypherx
+ xauth
+ 2.0
+ xAuth
+ http://www.bukkit.org
+
+
+ bukkit-repo
+
+ true
+
+
+ true
+
+ http://artifacts.lukegb.com/artifactory/repo/
+
+
+
+
+ org.bukkit
+ bukkit
+ 0.0.1-SNAPSHOT
+ jar
+ compile
+
+
+ com.nijikokun.bukkit
+ Permissions
+ [3.1,)
+ jar
+ compile
+
+
+ me.taylorkelly
+ Help
+ [2.4,)
+ jar
+ compile
+
+
+
+ ${project.name}
+
+
+ false
+ src/main/resources
+
+ plugin.yml
+
+
+
+ res
+ false
+ src/main/resources
+
+ config.yml
+ messages.yml
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+ UTF-8
+
+ 1.6
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 2.5
+
+ UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.3.1
+
+
+ src/main/resources/MANIFEST.MF
+
+
+
+
+ package
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/Account.java b/src/main/java/com/cypherx/xauth/Account.java
new file mode 100644
index 0000000..5f8ad34
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/Account.java
@@ -0,0 +1,108 @@
+package com.cypherx.xauth;
+
+import java.sql.Timestamp;
+
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+public class Account {
+ private int id = 0;
+ private String playerName;
+ private String password;
+ private String email;
+ private Timestamp registerDate;
+ private String registerHost;
+ private Timestamp lastLoginDate;
+ private String lastLoginHost;
+ private int active = 0;
+
+ public Account() {}
+
+ public Account(String playerName, String password, String email) {
+ this.playerName = playerName;
+ this.password = password;
+ this.email = email;
+ registerDate = Util.getNow();
+ registerHost = Util.getHostFromPlayer(getPlayer());
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setPlayerName(String playerName) {
+ this.playerName = playerName;
+ }
+
+ public String getPlayerName() {
+ return playerName;
+ }
+
+ public void setPlayer(Player player) {
+ this.playerName = player.getName();
+ }
+
+ public Player getPlayer() {
+ return Bukkit.getServer().getPlayer(playerName);
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setRegisterDate(Timestamp registerDate) {
+ this.registerDate = registerDate;
+ }
+
+ public Timestamp getRegisterDate() {
+ return registerDate;
+ }
+
+ public void setRegisterHost(String registerHost) {
+ this.registerHost = registerHost;
+ }
+
+ public String getRegisterHost() {
+ return registerHost;
+ }
+
+ public void setLastLoginDate(Timestamp lastLoginDate) {
+ this.lastLoginDate = lastLoginDate;
+ }
+
+ public Timestamp getLastLoginDate() {
+ return lastLoginDate;
+ }
+
+ public void setLastLoginHost(String lastLoginHost) {
+ this.lastLoginHost = lastLoginHost;
+ }
+
+ public String getLastLoginHost() {
+ return lastLoginHost;
+ }
+
+ public void setActive(int active) {
+ this.active = active;
+ }
+
+ public int getActive() {
+ return active;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/Session.java b/src/main/java/com/cypherx/xauth/Session.java
new file mode 100644
index 0000000..abede38
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/Session.java
@@ -0,0 +1,50 @@
+package com.cypherx.xauth;
+
+import java.sql.Timestamp;
+
+
+public class Session {
+ private int accountId;
+ private String host;
+ private Timestamp loginTime;
+
+ public Session() {}
+
+ public Session(int accountId, String host) {
+ this.accountId = accountId;
+ this.host = host;
+ loginTime = Util.getNow();
+ }
+
+ public boolean isExpired() {
+ Timestamp expireTime = new Timestamp(loginTime.getTime() + (xAuthSettings.sessionLength * 1000));
+ if (expireTime.compareTo(Util.getNow()) < 0)
+ return true;
+
+ return false;
+ }
+
+ public void setAccountId(int accountId) {
+ this.accountId = accountId;
+ }
+
+ public int getAccountId() {
+ return accountId;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setLoginTime(Timestamp loginTime) {
+ this.loginTime = loginTime;
+ }
+
+ public Timestamp getLoginTime() {
+ return loginTime;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/StrikeBan.java b/src/main/java/com/cypherx/xauth/StrikeBan.java
new file mode 100644
index 0000000..f432ab3
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/StrikeBan.java
@@ -0,0 +1,31 @@
+package com.cypherx.xauth;
+
+import java.sql.Timestamp;
+
+public class StrikeBan {
+ private String host;
+ private Timestamp banTime;
+
+ public StrikeBan() {}
+
+ public StrikeBan(String host) {
+ this.host = host;
+ banTime = Util.getNow();
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setBanTime(Timestamp banTime) {
+ this.banTime = banTime;
+ }
+
+ public Timestamp getBanTime() {
+ return banTime;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/TeleLocation.java b/src/main/java/com/cypherx/xauth/TeleLocation.java
new file mode 100644
index 0000000..f351321
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/TeleLocation.java
@@ -0,0 +1,88 @@
+package com.cypherx.xauth;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.World;
+
+public class TeleLocation {
+ private String worldName;
+ private double x;
+ private double y;
+ private double z;
+ private float yaw;
+ private float pitch;
+
+ public TeleLocation() {}
+
+ public TeleLocation(Location location) {
+ worldName = location.getWorld().getName();
+ x = location.getX();
+ y = location.getY();
+ z = location.getZ();
+ yaw = location.getYaw();
+ pitch = location.getPitch();
+ }
+
+ public void setWorldName(String worldName) {
+ this.worldName = worldName;
+ }
+
+ public String getWorldName() {
+ return worldName;
+ }
+
+ public void setX(double x) {
+ this.x = x;
+ }
+
+ public double getX() {
+ return x;
+ }
+
+ public void setY(double y) {
+ this.y = y;
+ }
+
+ public double getY() {
+ return y;
+ }
+
+ public void setZ(double z) {
+ this.z = z;
+ }
+
+ public double getZ() {
+ return z;
+ }
+
+ public void setYaw(float yaw) {
+ this.yaw = yaw;
+ }
+
+ public float getYaw() {
+ return yaw;
+ }
+
+ public void setPitch(float pitch) {
+ this.pitch = pitch;
+ }
+
+ public float getPitch() {
+ return pitch;
+ }
+
+ public void setLocation(Location location) {
+ this.worldName = location.getWorld().getName();
+ this.x = location.getX();
+ this.y = location.getY();
+ this.z = location.getZ();
+ this.yaw = location.getYaw();
+ this.pitch = location.getPitch();
+ }
+
+ public Location getLocation() {
+ World world = Bukkit.getServer().getWorld(worldName);
+ return new Location(world, x, y, z, yaw, pitch);
+ }
+}
+
diff --git a/src/main/java/com/cypherx/xauth/Util.java b/src/main/java/com/cypherx/xauth/Util.java
new file mode 100644
index 0000000..398f4c0
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/Util.java
@@ -0,0 +1,202 @@
+package com.cypherx.xauth;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.sql.Timestamp;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.bukkit.entity.Player;
+
+import com.avaje.ebean.validation.factory.EmailValidatorFactory;
+
+/*
+ * Miscellaneous methods
+ */
+
+public class Util {
+ public static void writeConfig(File file, Class> c) {
+ String fileName = file.getName();
+ String content = getResourceAsString(fileName);
+
+ for (Field field : c.getFields()) {
+ try {
+ content = content.replace("[" + field.getName() + "]", field.get(null).toString());
+ } catch (IllegalAccessException e) {}
+ }
+
+ BufferedWriter out = null;
+
+ try {
+ out = new BufferedWriter(new FileWriter(file));
+ out.write(content);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (out != null)
+ out.close();
+ } catch (IOException e) {}
+ }
+ }
+
+ private static String getResourceAsString(String resource) {
+ InputStream input = xAuth.class.getResourceAsStream("/res/" + resource);
+ StringBuilder sb = new StringBuilder();
+
+ if (input != null) {
+ InputStreamReader isr = new InputStreamReader(input);
+ BufferedReader br = new BufferedReader(isr);
+ String newLine = System.getProperty("line.separator");
+ String line;
+
+ try {
+ while ((line = br.readLine()) != null)
+ sb.append(line).append(newLine);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (isr != null)
+ isr.close();
+ } catch (IOException e) {}
+ try {
+ if (br != null)
+ br.close();
+ } catch (IOException e) {}
+ }
+ }
+
+ return sb.toString();
+ }
+
+ public static boolean getOnlineMode() {
+ BufferedReader br = null;
+ String value = null;
+ String line;
+
+ try {
+ br = new BufferedReader(new FileReader("server.properties"));
+ while ((line = br.readLine()).indexOf("online-mode") == -1);
+ value = line.split("=")[1];
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (br != null)
+ br.close();
+ } catch (IOException e) {}
+ }
+
+ return Boolean.parseBoolean(value);
+ }
+
+ public static boolean isValidName(Player player) {
+ String playerName = player.getName().toLowerCase();
+ if (playerName.length() < xAuthSettings.filterMinLength)
+ return false;
+
+ String allowed = xAuthSettings.filterAllowed;
+ if (!allowed.equals("*")) {
+ for(int i = 0; i < playerName.length(); i++) {
+ if (allowed.indexOf(playerName.charAt(i)) == -1)
+ return false;
+ }
+ }
+
+ if (xAuthSettings.filterBlank && playerName.trim().equals(""))
+ return false;
+
+ return true;
+ }
+
+ public static boolean isValidPass(String pass) {
+ String pattern = "(";
+
+ if (xAuthSettings.pwCompLower)
+ pattern += "(?=.*[a-z])";
+
+ if (xAuthSettings.pwCompUpper)
+ pattern += "(?=.*[A-Z])";
+
+ if (xAuthSettings.pwCompNumber)
+ pattern += "(?=.*\\d)";
+
+ if (xAuthSettings.pwCompSymbol)
+ pattern += "(?=.*\\W)";
+
+ pattern += ".{" + xAuthSettings.pwMinLength + ",})";
+ Pattern p = Pattern.compile(pattern);
+ Matcher matcher = p.matcher(pass);
+ return matcher.matches();
+ }
+
+ public static boolean isValidEmail(String email) {
+ return EmailValidatorFactory.EMAIL.isValid(email);
+ }
+
+ public static String encrypt(String pass) {
+ Whirlpool w = new Whirlpool();
+ byte[] digest = new byte[Whirlpool.DIGESTBYTES];
+
+ w.NESSIEinit();
+ w.NESSIEadd(UUID.randomUUID().toString());
+ w.NESSIEfinalize(digest);
+ String salt = Whirlpool.display(digest).substring(0, 8);
+
+ w.NESSIEinit();
+ w.NESSIEadd(salt + pass);
+ w.NESSIEfinalize(digest);
+ String hash = Whirlpool.display(digest);
+
+ int saltPos = (pass.length() >= hash.length() ? hash.length() : pass.length());
+ return hash.substring(0, saltPos) + salt + hash.substring(saltPos);
+ }
+
+ public static String whirlpool(String pass) {
+ Whirlpool w = new Whirlpool();
+ byte[] digest = new byte[Whirlpool.DIGESTBYTES];
+ w.NESSIEinit();
+ w.NESSIEadd(pass);
+ w.NESSIEfinalize(digest);
+ return Whirlpool.display(digest);
+ }
+
+ public static String md5(String pass) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] messageDigest = md.digest(pass.getBytes());
+ BigInteger number = new BigInteger(1, messageDigest);
+ String hashtext = number.toString(16);
+ while (hashtext.length() < 32)
+ hashtext = "0" + hashtext;
+
+ return hashtext;
+ } catch (Exception e) {
+ xAuthLog.severe("Could not create MD5 hash!", e);
+ }
+
+ return null;
+ }
+
+ public static String getHostFromPlayer(Player player) {
+ if (player == null)
+ return null;
+
+ return player.getAddress().getAddress().getHostAddress();
+ }
+
+ public static Timestamp getNow() {
+ return new Timestamp(System.currentTimeMillis());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/Whirlpool.java b/src/main/java/com/cypherx/xauth/Whirlpool.java
new file mode 100644
index 0000000..6305820
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/Whirlpool.java
@@ -0,0 +1,410 @@
+package com.cypherx.xauth;
+
+/**
+ * The Whirlpool hashing function.
+ *
+ *
+ * References
+ *
+ *
+ * The Whirlpool algorithm was developed by
+ * Paulo S. L. M. Barreto and
+ * Vincent Rijmen.
+ *
+ * See
+ * P.S.L.M. Barreto, V. Rijmen,
+ * ``The Whirlpool hashing function,''
+ * First NESSIE workshop, 2000 (tweaked version, 2003),
+ *
+ *
+ * @author Paulo S.L.M. Barreto
+ * @author Vincent Rijmen.
+ *
+ * @version 3.0 (2003.03.12)
+ *
+ * =============================================================================
+ *
+ * Differences from version 2.1:
+ *
+ * - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2, 9).
+ *
+ * =============================================================================
+ *
+ * Differences from version 2.0:
+ *
+ * - Generation of ISO/IEC 10118-3 test vectors.
+ * - Bug fix: nonzero carry was ignored when tallying the data length
+ * (this bug apparently only manifested itself when feeding data
+ * in pieces rather than in a single chunk at once).
+ *
+ * Differences from version 1.0:
+ *
+ * - Original S-box replaced by the tweaked, hardware-efficient version.
+ *
+ * =============================================================================
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+import java.util.Arrays;
+
+class Whirlpool {
+
+ /**
+ * The message digest size (in bits)
+ */
+ public static final int DIGESTBITS = 512;
+
+ /**
+ * The message digest size (in bytes)
+ */
+ public static final int DIGESTBYTES = DIGESTBITS >>> 3;
+
+ /**
+ * The number of rounds of the internal dedicated block cipher.
+ */
+ protected static final int R = 10;
+
+ /**
+ * The substitution box.
+ */
+ private static final String sbox =
+ "\u1823\uc6E8\u87B8\u014F\u36A6\ud2F5\u796F\u9152" +
+ "\u60Bc\u9B8E\uA30c\u7B35\u1dE0\ud7c2\u2E4B\uFE57" +
+ "\u1577\u37E5\u9FF0\u4AdA\u58c9\u290A\uB1A0\u6B85" +
+ "\uBd5d\u10F4\ucB3E\u0567\uE427\u418B\uA77d\u95d8" +
+ "\uFBEE\u7c66\udd17\u479E\ucA2d\uBF07\uAd5A\u8333" +
+ "\u6302\uAA71\uc819\u49d9\uF2E3\u5B88\u9A26\u32B0" +
+ "\uE90F\ud580\uBEcd\u3448\uFF7A\u905F\u2068\u1AAE" +
+ "\uB454\u9322\u64F1\u7312\u4008\uc3Ec\udBA1\u8d3d" +
+ "\u9700\ucF2B\u7682\ud61B\uB5AF\u6A50\u45F3\u30EF" +
+ "\u3F55\uA2EA\u65BA\u2Fc0\udE1c\uFd4d\u9275\u068A" +
+ "\uB2E6\u0E1F\u62d4\uA896\uF9c5\u2559\u8472\u394c" +
+ "\u5E78\u388c\ud1A5\uE261\uB321\u9c1E\u43c7\uFc04" +
+ "\u5199\u6d0d\uFAdF\u7E24\u3BAB\ucE11\u8F4E\uB7EB" +
+ "\u3c81\u94F7\uB913\u2cd3\uE76E\uc403\u5644\u7FA9" +
+ "\u2ABB\uc153\udc0B\u9d6c\u3174\uF646\uAc89\u14E1" +
+ "\u163A\u6909\u70B6\ud0Ed\ucc42\u98A4\u285c\uF886";
+
+ private static long[][] C = new long[8][256];
+ private static long[] rc = new long[R + 1];
+
+ static {
+ for (int x = 0; x < 256; x++) {
+ char c = sbox.charAt(x/2);
+ long v1 = ((x & 1) == 0) ? c >>> 8 : c & 0xff;
+ long v2 = v1 << 1;
+ if (v2 >= 0x100L) {
+ v2 ^= 0x11dL;
+ }
+ long v4 = v2 << 1;
+ if (v4 >= 0x100L) {
+ v4 ^= 0x11dL;
+ }
+ long v5 = v4 ^ v1;
+ long v8 = v4 << 1;
+ if (v8 >= 0x100L) {
+ v8 ^= 0x11dL;
+ }
+ long v9 = v8 ^ v1;
+ /*
+ * build the circulant table C[0][x] = S[x].[1, 1, 4, 1, 8, 5, 2, 9]:
+ */
+ C[0][x] =
+ (v1 << 56) | (v1 << 48) | (v4 << 40) | (v1 << 32) |
+ (v8 << 24) | (v5 << 16) | (v2 << 8) | (v9 );
+ /*
+ * build the remaining circulant tables C[t][x] = C[0][x] rotr t
+ */
+ for (int t = 1; t < 8; t++) {
+ C[t][x] = (C[t - 1][x] >>> 8) | ((C[t - 1][x] << 56));
+ }
+ }
+
+ /*
+ * build the round constants:
+ */
+ rc[0] = 0L; /* not used (assigment kept only to properly initialize all variables) */
+ for (int r = 1; r <= R; r++) {
+ int i = 8*(r - 1);
+ rc[r] =
+ (C[0][i ] & 0xff00000000000000L) ^
+ (C[1][i + 1] & 0x00ff000000000000L) ^
+ (C[2][i + 2] & 0x0000ff0000000000L) ^
+ (C[3][i + 3] & 0x000000ff00000000L) ^
+ (C[4][i + 4] & 0x00000000ff000000L) ^
+ (C[5][i + 5] & 0x0000000000ff0000L) ^
+ (C[6][i + 6] & 0x000000000000ff00L) ^
+ (C[7][i + 7] & 0x00000000000000ffL);
+ }
+ }
+
+ /**
+ * Global number of hashed bits (256-bit counter).
+ */
+ protected byte[] bitLength = new byte[32];
+
+ /**
+ * Buffer of data to hash.
+ */
+ protected byte[] buffer = new byte[64];
+
+ /**
+ * Current number of bits on the buffer.
+ */
+ protected int bufferBits = 0;
+
+ /**
+ * Current (possibly incomplete) byte slot on the buffer.
+ */
+ protected int bufferPos = 0;
+
+ /**
+ * The hashing state.
+ */
+ protected long[] hash = new long[8];
+ protected long[] K = new long[8]; // the round key
+ protected long[] L = new long[8];
+ protected long[] block = new long[8]; // mu(buffer)
+ protected long[] state = new long[8]; // the cipher state
+
+ public Whirlpool() {
+ }
+
+ /**
+ * The core Whirlpool transform.
+ */
+ protected void processBuffer() {
+ /*
+ * map the buffer to a block:
+ */
+ for (int i = 0, j = 0; i < 8; i++, j += 8) {
+ block[i] =
+ (((long)buffer[j ] ) << 56) ^
+ (((long)buffer[j + 1] & 0xffL) << 48) ^
+ (((long)buffer[j + 2] & 0xffL) << 40) ^
+ (((long)buffer[j + 3] & 0xffL) << 32) ^
+ (((long)buffer[j + 4] & 0xffL) << 24) ^
+ (((long)buffer[j + 5] & 0xffL) << 16) ^
+ (((long)buffer[j + 6] & 0xffL) << 8) ^
+ (((long)buffer[j + 7] & 0xffL) );
+ }
+ /*
+ * compute and apply K^0 to the cipher state:
+ */
+ for (int i = 0; i < 8; i++) {
+ state[i] = block[i] ^ (K[i] = hash[i]);
+ }
+ /*
+ * iterate over all rounds:
+ */
+ for (int r = 1; r <= R; r++) {
+ /*
+ * compute K^r from K^{r-1}:
+ */
+ for (int i = 0; i < 8; i++) {
+ L[i] = 0L;
+ for (int t = 0, s = 56; t < 8; t++, s -= 8) {
+ L[i] ^= C[t][(int)(K[(i - t) & 7] >>> s) & 0xff];
+ }
+ }
+ for (int i = 0; i < 8; i++) {
+ K[i] = L[i];
+ }
+ K[0] ^= rc[r];
+ /*
+ * apply the r-th round transformation:
+ */
+ for (int i = 0; i < 8; i++) {
+ L[i] = K[i];
+ for (int t = 0, s = 56; t < 8; t++, s -= 8) {
+ L[i] ^= C[t][(int)(state[(i - t) & 7] >>> s) & 0xff];
+ }
+ }
+ for (int i = 0; i < 8; i++) {
+ state[i] = L[i];
+ }
+ }
+ /*
+ * apply the Miyaguchi-Preneel compression function:
+ */
+ for (int i = 0; i < 8; i++) {
+ hash[i] ^= state[i] ^ block[i];
+ }
+ }
+
+ /**
+ * Initialize the hashing state.
+ */
+ public void NESSIEinit() {
+ Arrays.fill(bitLength, (byte)0);
+ bufferBits = bufferPos = 0;
+ buffer[0] = 0; // it's only necessary to cleanup buffer[bufferPos].
+ Arrays.fill(hash, 0L); // initial value
+ }
+
+ /**
+ * Delivers input data to the hashing algorithm.
+ *
+ * @param source plaintext data to hash.
+ * @param sourceBits how many bits of plaintext to process.
+ *
+ * This method maintains the invariant: bufferBits < 512
+ */
+ public void NESSIEadd(byte[] source, long sourceBits) {
+ /*
+ sourcePos
+ |
+ +-------+-------+-------
+ ||||||||||||||||||||| source
+ +-------+-------+-------
+ +-------+-------+-------+-------+-------+-------
+ |||||||||||||||||||||| buffer
+ +-------+-------+-------+-------+-------+-------
+ |
+ bufferPos
+ */
+ int sourcePos = 0; // index of leftmost source byte containing data (1 to 8 bits).
+ int sourceGap = (8 - ((int)sourceBits & 7)) & 7; // space on source[sourcePos].
+ int bufferRem = bufferBits & 7; // occupied bits on buffer[bufferPos].
+ int b;
+ // tally the length of the added data:
+ long value = sourceBits;
+ for (int i = 31, carry = 0; i >= 0; i--) {
+ carry += (bitLength[i] & 0xff) + ((int)value & 0xff);
+ bitLength[i] = (byte)carry;
+ carry >>>= 8;
+ value >>>= 8;
+ }
+ // process data in chunks of 8 bits:
+ while (sourceBits > 8) { // at least source[sourcePos] and source[sourcePos+1] contain data.
+ // take a byte from the source:
+ b = ((source[sourcePos] << sourceGap) & 0xff) |
+ ((source[sourcePos + 1] & 0xff) >>> (8 - sourceGap));
+ if (b < 0 || b >= 256) {
+ throw new RuntimeException("LOGIC ERROR");
+ }
+ // process this byte:
+ buffer[bufferPos++] |= b >>> bufferRem;
+ bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos;
+ if (bufferBits == 512) {
+ // process data block:
+ processBuffer();
+ // reset buffer:
+ bufferBits = bufferPos = 0;
+ }
+ buffer[bufferPos] = (byte)((b << (8 - bufferRem)) & 0xff);
+ bufferBits += bufferRem;
+ // proceed to remaining data:
+ sourceBits -= 8;
+ sourcePos++;
+ }
+ // now 0 <= sourceBits <= 8;
+ // furthermore, all data (if any is left) is in source[sourcePos].
+ if (sourceBits > 0) {
+ b = (source[sourcePos] << sourceGap) & 0xff; // bits are left-justified on b.
+ // process the remaining bits:
+ buffer[bufferPos] |= b >>> bufferRem;
+ } else {
+ b = 0;
+ }
+ if (bufferRem + sourceBits < 8) {
+ // all remaining data fits on buffer[bufferPos], and there still remains some space.
+ bufferBits += sourceBits;
+ } else {
+ // buffer[bufferPos] is full:
+ bufferPos++;
+ bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos;
+ sourceBits -= 8 - bufferRem;
+ // now 0 <= sourceBits < 8; furthermore, all data is in source[sourcePos].
+ if (bufferBits == 512) {
+ // process data block:
+ processBuffer();
+ // reset buffer:
+ bufferBits = bufferPos = 0;
+ }
+ buffer[bufferPos] = (byte)((b << (8 - bufferRem)) & 0xff);
+ bufferBits += (int)sourceBits;
+ }
+ }
+
+ /**
+ * Get the hash value from the hashing state.
+ *
+ * This method uses the invariant: bufferBits < 512
+ */
+ public void NESSIEfinalize(byte[] digest) {
+ // append a '1'-bit:
+ buffer[bufferPos] |= 0x80 >>> (bufferBits & 7);
+ bufferPos++; // all remaining bits on the current byte are set to zero.
+ // pad with zero bits to complete 512N + 256 bits:
+ if (bufferPos > 32) {
+ while (bufferPos < 64) {
+ buffer[bufferPos++] = 0;
+ }
+ // process data block:
+ processBuffer();
+ // reset buffer:
+ bufferPos = 0;
+ }
+ while (bufferPos < 32) {
+ buffer[bufferPos++] = 0;
+ }
+ // append bit length of hashed data:
+ System.arraycopy(bitLength, 0, buffer, 32, 32);
+ // process data block:
+ processBuffer();
+ // return the completed message digest:
+ for (int i = 0, j = 0; i < 8; i++, j += 8) {
+ long h = hash[i];
+ digest[j ] = (byte)(h >>> 56);
+ digest[j + 1] = (byte)(h >>> 48);
+ digest[j + 2] = (byte)(h >>> 40);
+ digest[j + 3] = (byte)(h >>> 32);
+ digest[j + 4] = (byte)(h >>> 24);
+ digest[j + 5] = (byte)(h >>> 16);
+ digest[j + 6] = (byte)(h >>> 8);
+ digest[j + 7] = (byte)(h );
+ }
+ }
+
+ /**
+ * Delivers string input data to the hashing algorithm.
+ *
+ * @param source plaintext data to hash (ASCII text string).
+ *
+ * This method maintains the invariant: bufferBits < 512
+ */
+ public void NESSIEadd(String source) {
+ if (source.length() > 0) {
+ byte[] data = new byte[source.length()];
+ for (int i = 0; i < source.length(); i++) {
+ data[i] = (byte)source.charAt(i);
+ }
+ NESSIEadd(data, 8*data.length);
+ }
+ }
+
+ public static String display(byte[] array) {
+ char[] val = new char[2*array.length];
+ //String hex = "0123456789ABCDEF";
+ String hex = "0123456789abcdef";
+ for (int i = 0; i < array.length; i++) {
+ int b = array[i] & 0xff;
+ val[2*i] = hex.charAt(b >>> 4);
+ val[2*i + 1] = hex.charAt(b & 15);
+ }
+ return String.valueOf(val);
+ }
+}
diff --git a/src/main/java/com/cypherx/xauth/commands/ChangePasswordCommand.java b/src/main/java/com/cypherx/xauth/commands/ChangePasswordCommand.java
new file mode 100644
index 0000000..d3e75a4
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/commands/ChangePasswordCommand.java
@@ -0,0 +1,58 @@
+package com.cypherx.xauth.commands;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import com.cypherx.xauth.Account;
+import com.cypherx.xauth.Util;
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthLog;
+import com.cypherx.xauth.xAuthMessages;
+import com.cypherx.xauth.xAuthPlayer;
+import com.cypherx.xauth.xAuthSettings;
+
+public class ChangePasswordCommand implements CommandExecutor {
+ private final xAuth plugin;
+
+ public ChangePasswordCommand(xAuth plugin) {
+ this.plugin = plugin;
+ }
+
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(player.getName());
+
+ if (!xAuthSettings.pwAllowChange) {
+ xAuthMessages.send("cpwErrDisabled", player);
+ return true;
+ } else if (!xPlayer.hasSession()) {
+ xAuthMessages.send("cpwErrLogged", player);
+ return true;
+ } else if (args.length < 2) {
+ xAuthMessages.send("cpwUsage", player);
+ return true;
+ }
+
+ Account account = xPlayer.getAccount();
+ String oldPassword = args[0];
+ String newPassword = args[1];
+
+ if (!plugin.checkPassword(account, oldPassword)) {
+ xAuthMessages.send("cpwErrIncorrect", player);
+ return true;
+ } else if (!Util.isValidPass(newPassword)) {
+ xAuthMessages.send("cpwErrInvalid", player);
+ return true;
+ }
+
+ plugin.changePassword(account, newPassword);
+ xAuthMessages.send("cpwSuccess", player);
+ xAuthLog.info(player.getName() + " changed their password");
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/commands/LoginCommand.java b/src/main/java/com/cypherx/xauth/commands/LoginCommand.java
new file mode 100644
index 0000000..d74d7d5
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/commands/LoginCommand.java
@@ -0,0 +1,62 @@
+package com.cypherx.xauth.commands;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import com.cypherx.xauth.Account;
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthLog;
+import com.cypherx.xauth.xAuthMessages;
+import com.cypherx.xauth.xAuthPlayer;
+import com.cypherx.xauth.xAuthSettings;
+
+public class LoginCommand implements CommandExecutor {
+ private final xAuth plugin;
+
+ public LoginCommand(xAuth plugin) {
+ this.plugin = plugin;
+ }
+
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(player.getName());
+
+ if (args.length < 1) {
+ xAuthMessages.send("loginUsage", player);
+ return true;
+ } else if (!xPlayer.isRegistered()) {
+ xAuthMessages.send("loginErrRegistered", player);
+ return true;
+ } else if (xPlayer.hasSession()) {
+ xAuthMessages.send("loginErrLogged", player);
+ return true;
+ }
+
+ Account account = xPlayer.getAccount();
+ String password = args[0];
+
+ if (!plugin.checkPassword(account, password)) {
+ if (xAuthSettings.maxStrikes > 0) {
+ xPlayer.setStrikes(xPlayer.getStrikes() + 1);
+ if (xPlayer.getStrikes() >= xAuthSettings.maxStrikes)
+ plugin.strikeout(xPlayer);
+ }
+
+ xAuthMessages.send("loginErrPassword", player);
+ return true;
+ } else if (xAuthSettings.activation && account.getActive() == 0) {
+ xAuthMessages.send("loginErrActivate", player);
+ return true;
+ }
+
+ plugin.login(xPlayer);
+ xAuthMessages.send("loginSuccess", player);
+ xAuthLog.info(player.getName() + " has logged in");
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/commands/LogoutCommand.java b/src/main/java/com/cypherx/xauth/commands/LogoutCommand.java
new file mode 100644
index 0000000..a8b93a2
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/commands/LogoutCommand.java
@@ -0,0 +1,35 @@
+package com.cypherx.xauth.commands;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthMessages;
+import com.cypherx.xauth.xAuthPlayer;
+
+public class LogoutCommand implements CommandExecutor {
+ private final xAuth plugin;
+
+ public LogoutCommand(xAuth plugin) {
+ this.plugin = plugin;
+ }
+
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(player.getName());
+
+ if (!xPlayer.hasSession()) {
+ xAuthMessages.send("logoutErrLogged", player);
+ return true;
+ }
+
+ plugin.createGuest(xPlayer);
+ xAuthMessages.send("logoutSuccess", player);
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/commands/RegisterCommand.java b/src/main/java/com/cypherx/xauth/commands/RegisterCommand.java
new file mode 100644
index 0000000..6269229
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/commands/RegisterCommand.java
@@ -0,0 +1,62 @@
+package com.cypherx.xauth.commands;
+
+import com.cypherx.xauth.Account;
+import com.cypherx.xauth.Util;
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthLog;
+import com.cypherx.xauth.xAuthMessages;
+import com.cypherx.xauth.xAuthPlayer;
+import com.cypherx.xauth.xAuthSettings;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class RegisterCommand implements CommandExecutor {
+ private final xAuth plugin;
+
+ public RegisterCommand(xAuth plugin) {
+ this.plugin = plugin;
+ }
+
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(player.getName());
+
+ if (!xAuthSettings.regEnabled) {
+ xAuthMessages.send("regErrDisabled", player);
+ return true;
+ } else if ((xAuthSettings.requireEmail && args.length < 2) || args.length < 1) {
+ xAuthMessages.send("regUsage", player);
+ return true;
+ } else if (xPlayer.isRegistered()) {
+ xAuthMessages.send("regErrRegistered", player);
+ return true;
+ } else if (!xAuthSettings.allowMultiple && plugin.getDataManager().isHostUsed(Util.getHostFromPlayer(player))) {
+ xAuthMessages.send("regErrMultiple", player);
+ return true;
+ }
+
+ String password = args[0];
+ String email = (args.length > 1 ? args[1] : null);
+
+ if (!Util.isValidPass(password)) {
+ xAuthMessages.send("regErrPassword", player);
+ return true;
+ } else if (xAuthSettings.validateEmail && !Util.isValidEmail(email)) {
+ xAuthMessages.send("regErrEmail", player);
+ return true;
+ }
+
+ xPlayer.setAccount(new Account(player.getName(), Util.encrypt(password), email));
+ plugin.login(xPlayer);
+
+ xAuthMessages.send("regSuccess", player);
+ xAuthLog.info(player.getName() + " has registered!");
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/cypherx/xauth/commands/xAuthCommand.java b/src/main/java/com/cypherx/xauth/commands/xAuthCommand.java
new file mode 100644
index 0000000..0656c7f
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/commands/xAuthCommand.java
@@ -0,0 +1,445 @@
+package com.cypherx.xauth.commands;
+
+import java.lang.reflect.Field;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.ConsoleCommandSender;
+import org.bukkit.entity.Player;
+
+import com.cypherx.xauth.Account;
+import com.cypherx.xauth.TeleLocation;
+import com.cypherx.xauth.Util;
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthLog;
+import com.cypherx.xauth.xAuthMessages;
+import com.cypherx.xauth.xAuthPermissions;
+import com.cypherx.xauth.xAuthPlayer;
+import com.cypherx.xauth.xAuthSettings;
+import com.cypherx.xauth.datamanager.DataManager;
+
+public class xAuthCommand implements CommandExecutor {
+ private final xAuth plugin;
+ private DataManager dataManager;
+
+ public xAuthCommand(xAuth plugin) {
+ this.plugin = plugin;
+ this.dataManager = plugin.getDataManager();
+ }
+
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (args.length < 1)
+ return false;
+
+ String subCommand = args[0];
+ if (subCommand.equals("register"))
+ return registerCommand(sender, args);
+ else if (subCommand.equals("changepw") || subCommand.equals("cpw") || subCommand.equals("changepassword") || subCommand.equals("changepass"))
+ return changePasswordCommand(sender, args);
+ else if (subCommand.equals("logout"))
+ return logoutCommand(sender, args);
+ else if (subCommand.equals("unregister"))
+ return unregisterCommand(sender, args);
+ else if (subCommand.equals("location") || subCommand.equals("loc"))
+ return locationCommand(sender, args);
+ else if (subCommand.equals("config") || subCommand.equals("conf"))
+ return configCommand(sender, args);
+ else if (subCommand.equals("reload"))
+ return reloadCommand(sender);
+ else {
+ if (sender instanceof Player)
+ xAuthMessages.send("admnUnknown", (Player)sender);
+ else if (sender instanceof ConsoleCommandSender)
+ xAuthLog.info("Unknown subcommand, try \"xauth\" for more information");
+ }
+
+ return true;
+ }
+
+ private boolean registerCommand(CommandSender sender, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+
+ if (!xAuthPermissions.has(player, "xauth.admin.register")) {
+ xAuthMessages.send("admnPermission", player);
+ return true;
+ } else if (args.length < 3) {
+ xAuthMessages.send("admnRegUsage", player);
+ return true;
+ }
+
+ String targetName = args[1];
+ String password = args[2];
+ String email = (args.length > 3 ? args[3] : null);
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(targetName);
+
+ if (xPlayer.isRegistered()) {
+ xAuthMessages.send("admnRegRegistered", player, xPlayer.getPlayer());
+ return true;
+ }
+
+ Account account = new Account(targetName, Util.encrypt(password), email);
+ xPlayer.setAccount(account);
+ dataManager.saveAccount(account);
+
+ xAuthMessages.send("admnRegSuccess", player, xPlayer.getPlayer());
+ xAuthLog.info(player.getName() + " has registered an account for " + targetName);
+ } else if (sender instanceof ConsoleCommandSender) {
+ if (args.length < 3) {
+ xAuthLog.info("Correct Usage: xauth register [email]");
+ return true;
+ }
+
+ String targetName = args[1];
+ String password = args[2];
+ String email = (args.length > 3 ? args[3] : null);
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(targetName);
+
+ if (xPlayer.isRegistered()) {
+ xAuthLog.info(targetName + " is already registered!");
+ return true;
+ }
+
+ Account account = new Account(targetName, Util.encrypt(password), email);
+ xPlayer.setAccount(account);
+ dataManager.saveAccount(account);
+
+ xAuthLog.info("Account successfully created for: " + targetName);
+ }
+
+ return true;
+ }
+
+ private boolean changePasswordCommand(CommandSender sender, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+
+ if (!xAuthPermissions.has(player, "xauth.admin.changepw")) {
+ xAuthMessages.send("admnPermission", player);
+ return true;
+ } else if (args.length < 3) {
+ xAuthMessages.send("admnCpwUsage", player);
+ return true;
+ }
+
+ String targetName = args[1];
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(targetName);
+
+ if (!xPlayer.isRegistered()) {
+ xAuthMessages.send("admnCpwRegistered", player, xPlayer.getPlayer());
+ return true;
+ }
+
+ Account targetAcc = xPlayer.getAccount();
+ String newPassword = args[2];
+
+ plugin.changePassword(targetAcc, newPassword);
+ xAuthMessages.send("admnCpwSuccess", player, xPlayer.getPlayer());
+ xAuthLog.info(player.getName() + " changed " + targetName + "'s password");
+ } else if (sender instanceof ConsoleCommandSender) {
+ if (args.length < 3) {
+ xAuthLog.info("Correct Usage: xauth changepw ");
+ return true;
+ }
+
+ String targetName = args[1];
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(targetName);
+
+ if (!xPlayer.isRegistered()) {
+ xAuthLog.info("This player is not registered!");
+ return true;
+ }
+
+ Account targetAcc = xPlayer.getAccount();
+ String newPassword = args[2];
+
+ plugin.changePassword(targetAcc, newPassword);
+ xAuthLog.info(targetName + "'s password has been changed");
+ }
+
+ return true;
+ }
+
+ private boolean logoutCommand(CommandSender sender, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+
+ if (!xAuthPermissions.has(player, "xauth.admin.logout")) {
+ xAuthMessages.send("admnPermission", player);
+ return true;
+ } else if (args.length < 2) {
+ xAuthMessages.send("admnLogoutUsage", player);
+ return true;
+ }
+
+ String targetName = args[1];
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(targetName);
+
+ if (!xPlayer.hasSession()) {
+ xAuthMessages.send("admnLogoutLogged", player, xPlayer.getPlayer());
+ return true;
+ }
+
+ plugin.createGuest(xPlayer);
+ Player target = xPlayer.getPlayer();
+ xAuthMessages.send("admnLogoutSuccess", player, target);
+ if (target != null)
+ xAuthMessages.send("logoutSuccess", target);
+ xAuthLog.info(targetName + " was logged out by " + player.getName());
+ } else if (sender instanceof ConsoleCommandSender) {
+ if (args.length < 2) {
+ xAuthLog.info("Correct Usage: xauth logout ");
+ return true;
+ }
+
+ String targetName = args[1];
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(targetName);
+
+ if (!xPlayer.hasSession()) {
+ xAuthLog.info(targetName + " is not logged in!");
+ return true;
+ }
+
+ plugin.createGuest(xPlayer);
+ xAuthLog.info(targetName + " has been logged out");
+ Player target = xPlayer.getPlayer();
+ if (target != null)
+ xAuthMessages.send("logoutSuccess", target);
+ }
+
+ return true;
+ }
+
+ private boolean unregisterCommand(CommandSender sender, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+
+ if (!xAuthPermissions.has(player, "xauth.admin.unregister")) {
+ xAuthMessages.send("admnPermission", player);
+ return true;
+ } else if (args.length < 2) {
+ xAuthMessages.send("admnUnregUsage", player);
+ return true;
+ }
+
+ String targetName = args[1];
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(targetName);
+
+ if (!xPlayer.isRegistered()) {
+ xAuthMessages.send("admnUnregRegistered", player, xPlayer.getPlayer());
+ return true;
+ }
+
+ dataManager.deleteAccount(xPlayer);
+
+ Player target = xPlayer.getPlayer();
+ if (target != null) {
+ plugin.createGuest(xPlayer);
+ xAuthMessages.send("admnUnregSuccessTgt", target);
+ }
+
+ xAuthMessages.send("admnUnregSuccessPlyr", player, target);
+ xAuthLog.info(targetName + " has been unregistered by " + player.getName());
+ } else if (sender instanceof ConsoleCommandSender) {
+ if (args.length < 2) {
+ xAuthLog.info("Correct Usage: xauth unregister ");
+ return true;
+ }
+
+ String targetName = args[1];
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(targetName);
+
+ if (!xPlayer.isRegistered()) {
+ xAuthLog.info(targetName + " is not registered!");
+ return true;
+ }
+
+ dataManager.deleteAccount(xPlayer);
+
+ Player target = xPlayer.getPlayer();
+ if (target != null) {
+ plugin.createGuest(xPlayer);
+ target.sendMessage("You have been unregistered and logged out!");
+ }
+
+ xAuthLog.info(targetName + " has been unregistered!");
+ }
+
+ return true;
+ }
+
+ private boolean locationCommand(CommandSender sender, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+
+ if (!xAuthPermissions.has(player, "xauth.admin.location")) {
+ xAuthMessages.send("admnPermission", player);
+ return true;
+ } else if (args.length < 2 || !(args[1].equals("set") || args[1].equals("remove"))) {
+ xAuthMessages.send("admnLocUsage", player);
+ return true;
+ }
+
+ String action = args[1];
+
+ if (action.equals("set")) {
+ dataManager.setTeleLocation(new TeleLocation(player.getLocation()));
+ xAuthMessages.send("admnLocSetSuccess", player);
+ } else {
+ TeleLocation tLoc = dataManager.getTeleLocation(player.getWorld().getName());
+ if (tLoc == null) {
+ xAuthMessages.send("admnLocRmvNo", player);
+ return true;
+ }
+
+ dataManager.removeTeleLocation(tLoc);
+ xAuthMessages.send("admnLocRmvSuccess", player);
+ }
+ }
+
+ return true;
+ }
+
+ private boolean configCommand(CommandSender sender, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+
+ if (!xAuthPermissions.has(player, "xauth.admin.config")) {
+ xAuthMessages.send("admnPermission", player);
+ return true;
+ } else if (args.length < 2) {
+ xAuthMessages.send("admnConfUsage", player);
+ return true;
+ }
+
+ String setting = args[1];
+ Object value = (args.length > 2 ? args[2] : null);
+ Field field;
+
+ try {
+ field = xAuthSettings.class.getField(setting);
+ } catch (NoSuchFieldException e) {
+ xAuthMessages.send("admnConfNo", player);
+ return true;
+ }
+
+ String type = null;
+ if (field.getType().equals(String.class))
+ type = "String";
+ else if (field.getType().equals(Integer.TYPE))
+ type = "Integer";
+ else if (field.getType().equals(Boolean.TYPE))
+ type = "Boolean";
+
+ if (value == null) { // view setting info
+ //player.sendMessage("Setting: " + field.getName());
+ //player.sendMessage("Type: " + type);
+ try {
+ xAuthMessages.sendConfigDesc(player, field.getName(), type, field.get(xAuthSettings.class));
+ //player.sendMessage("Value: " + field.get(xAuthSettings.class));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ return true;
+ } else { // change setting
+ try {
+ if (type.equals("String"))
+ field.set(xAuthSettings.class, value.toString());
+ else if (type.equals("Integer"))
+ field.set(xAuthSettings.class, Integer.parseInt(value.toString()));
+ else if (type.equals("Boolean"))
+ field.set(xAuthSettings.class, Boolean.parseBoolean(value.toString()));
+ else
+ throw new IllegalArgumentException();
+ } catch (IllegalArgumentException e) {
+ xAuthMessages.send("admnConfInvalid", player);
+ return true;
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ return true;
+ }
+
+ xAuthSettings.changed = true;
+ xAuthMessages.send("admnConfSuccess", player);
+ xAuthLog.info(player.getName() + " has changed setting " + setting + " to " + value);
+ }
+ } else if (sender instanceof ConsoleCommandSender) {
+ if (args.length < 2) {
+ xAuthLog.info("Correct Usage: xauth config [new value]");
+ return true;
+ }
+
+ String setting = args[1];
+ Object value = (args.length > 2 ? args[2] : null);
+ Field field = null;
+
+ try {
+ field = xAuthSettings.class.getField(setting);
+ } catch (NoSuchFieldException e) {
+ xAuthLog.info("No such setting!");
+ return true;
+ }
+
+ String type = null;
+ if (field.getType().equals(String.class))
+ type = "String";
+ else if (field.getType().equals(Integer.TYPE))
+ type = "Integer";
+ else if (field.getType().equals(Boolean.TYPE))
+ type = "Boolean";
+
+ if (value == null) { // view setting info
+ xAuthLog.info("Setting: " + field.getName());
+ xAuthLog.info("Type: " + type);
+ try {
+ xAuthLog.info("Value: " + field.get(xAuthSettings.class));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ return true;
+ }
+ } else { // change setting
+ try {
+ if (type.equals("String"))
+ field.set(xAuthSettings.class, value.toString());
+ else if (type.equals("Integer"))
+ field.set(xAuthSettings.class, Integer.parseInt(value.toString()));
+ else if (type.equals("Boolean"))
+ field.set(xAuthSettings.class, Boolean.parseBoolean(value.toString()));
+ else
+ throw new IllegalArgumentException();
+ } catch (IllegalArgumentException e) {
+ xAuthLog.info("Invalid type");
+ return true;
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ return true;
+ }
+
+ xAuthSettings.changed = true;
+ xAuthLog.info("Setting changed!");
+ }
+ }
+
+ return true;
+ }
+
+ private boolean reloadCommand(CommandSender sender) {
+ if (sender instanceof Player) {
+ Player player = (Player)sender;
+
+ if (xAuthPermissions.has(player, "xauth.admin.reload")) {
+ plugin.reload();
+ xAuthMessages.send("admnReloadSuccess", player);
+ xAuthLog.info("Reloaded by " + player.getName());
+ } else
+ xAuthMessages.send("admnPermission", player);
+ } else if (sender instanceof ConsoleCommandSender) {
+ plugin.reload();
+ xAuthLog.info("Reload complete!");
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/datamanager/DataManager.java b/src/main/java/com/cypherx/xauth/datamanager/DataManager.java
new file mode 100644
index 0000000..65f7341
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/datamanager/DataManager.java
@@ -0,0 +1,577 @@
+package com.cypherx.xauth.datamanager;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.cypherx.xauth.Account;
+import com.cypherx.xauth.Session;
+import com.cypherx.xauth.StrikeBan;
+import com.cypherx.xauth.TeleLocation;
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthLog;
+import com.cypherx.xauth.xAuthPlayer;
+import com.cypherx.xauth.xAuthSettings;
+
+public class DataManager {
+ private Connection connection = null;
+ private Statement stmt = null;
+ private PreparedStatement prepStmt = null;
+ private ResultSet rs = null;
+
+ private ConcurrentHashMap playerCache = new ConcurrentHashMap();
+ private ConcurrentHashMap teleLocations = new ConcurrentHashMap();
+
+ public DataManager() {
+ if (xAuthSettings.datasource.equals("mysql"))
+ connectMySQL();
+ else
+ connectH2();
+ }
+
+ private void connectMySQL() {
+ try {
+ Class.forName("com.mysql.jdbc.Driver");
+ connection = DriverManager.getConnection("jdbc:mysql://" + xAuthSettings.mysqlHost + ":" + xAuthSettings.mysqlPort + "/" +
+ xAuthSettings.mysqlDb, xAuthSettings.mysqlUser, xAuthSettings.mysqlPass);
+ stmt = connection.createStatement();
+ xAuthLog.info("Connection to MySQL server established!");
+ } catch (ClassNotFoundException e) {
+ xAuthLog.severe("Missing MySQL library!", e);
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not connect to MySQL server!", e);
+ }
+ }
+
+ private void connectH2() {
+ if (!xAuthSettings.datasource.equals("default"))
+ System.out.println("[" + xAuth.desc.getName() + "] Unknown datasource '" + xAuthSettings.datasource + "' - Using default (H2)");
+
+ try {
+ Class.forName("org.h2.Driver");
+ connection = DriverManager.getConnection("jdbc:h2:" + xAuth.dataFolder.toString() +
+ System.getProperty("file.separator") + "xAuth;IGNORECASE=TRUE", "sa", "");
+ stmt = connection.createStatement();
+ xAuthLog.info("Connection to H2 database established!");
+ } catch (ClassNotFoundException e) {
+ xAuthLog.severe("Missing H2 library!", e);
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not connect to H2 database!", e);
+ }
+ }
+
+ public void runStartupTasks() {
+ createTables();
+ loadTeleLocations();
+
+ String sql;
+
+ if (xAuthSettings.datasource.equals("mysql")) {
+ sql = "DELETE FROM `" + xAuthSettings.tblSession + "`" +
+ "WHERE NOW() > ADDDATE(`logintime`, INTERVAL " + xAuthSettings.sessionLength + " SECOND)";
+ } else {
+ sql = "DELETE FROM `" + xAuthSettings.tblSession + "`" +
+ "WHERE NOW() > DATEADD('SECOND', " + xAuthSettings.sessionLength + ", `logintime`)";
+ }
+
+ // delete expired sessions
+ try {
+ stmt.executeUpdate(sql);
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not delete expired settings!", e);
+ }
+ }
+
+ public void printStats() {
+ try {
+ rs = stmt.executeQuery(
+ "SELECT" +
+ " (SELECT COUNT(*) FROM `" + xAuthSettings.tblAccount + "`) AS accounts," +
+ " (SELECT COUNT(*) FROM `" + xAuthSettings.tblSession + "`) AS sessions"
+ );
+
+ if (rs.next())
+ xAuthLog.info("Accounts: " + rs.getInt("accounts") + ", Sessions: " + rs.getInt("sessions"));
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not fetch xAuth statistics!", e);
+ }
+ }
+
+ public void createTables() {
+ try {
+ stmt.execute(
+ "CREATE TABLE IF NOT EXISTS `" + xAuthSettings.tblAccount + "` (" +
+ "`id` INT UNSIGNED NOT NULL AUTO_INCREMENT," +
+ "`playername` VARCHAR(255) NOT NULL," +
+ "`password` CHAR(255) NOT NULL," +
+ "`email` VARCHAR(100) NULL," +
+ "`registerdate` DATETIME NULL," +
+ "`registerip` CHAR(15) NULL," +
+ "`lastlogindate` DATETIME NULL," +
+ "`lastloginip` CHAR(15) NULL," +
+ "`active` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0," +
+ "PRIMARY KEY(`id`)" +
+ ")"
+ );
+
+ stmt.execute(
+ "CREATE TABLE IF NOT EXISTS `" + xAuthSettings.tblSession + "` (" +
+ "`accountid` INT UNSIGNED NOT NULL," +
+ "`host` CHAR(15) NOT NULL," +
+ "`logintime` DATETIME NOT NULL," +
+ "PRIMARY KEY(`accountid`)," +
+ "FOREIGN KEY (`accountid`) REFERENCES `" + xAuthSettings.tblAccount + "`(`id`) ON DELETE CASCADE" +
+ ")"
+ );
+
+ stmt.execute(
+ "CREATE TABLE IF NOT EXISTS `" + xAuthSettings.tblLocation + "` (" +
+ "`worldname` VARCHAR(255) NOT NULL," +
+ "`x` DOUBLE NOT NULL," +
+ "`y` DOUBLE NOT NULL," +
+ "`z` DOUBLE NOT NULL," +
+ "`yaw` FLOAT NOT NULL," +
+ "`pitch` FLOAT NOT NULL," +
+ "PRIMARY KEY(`worldname`)" +
+ ")"
+ );
+
+ stmt.execute(
+ "CREATE TABLE IF NOT EXISTS `" + xAuthSettings.tblStrike + "` (" +
+ "`host` CHAR(15) NOT NULL," +
+ "`bantime` DATETIME NOT NULL," +
+ "PRIMARY KEY(`host`)" +
+ ")"
+ );
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not check/create database tables!", e);
+ }
+ }
+
+ public xAuthPlayer getPlayerByName(String playerName) {
+ String lowPlayerName = playerName.toLowerCase();
+
+ if (playerCache.containsKey(lowPlayerName))
+ return playerCache.get(lowPlayerName);
+
+ xAuthPlayer xPlayer = getPlayerFromDb(playerName);
+ if (xPlayer == null)
+ xPlayer = new xAuthPlayer(playerName);
+
+ playerCache.put(lowPlayerName, xPlayer);
+ return xPlayer;
+ }
+
+ public xAuthPlayer getPlayerFromDb(String playerName) {
+ xAuthPlayer xPlayer = null;
+
+ try {
+ prepStmt = connection.prepareStatement(
+ "SELECT a.*, s.*" +
+ " FROM `" + xAuthSettings.tblAccount + "` a" +
+ " LEFT JOIN `" + xAuthSettings.tblSession + "` s" +
+ " ON a.id = s.accountid" +
+ " WHERE `playername` = ?"
+ );
+ prepStmt.setString(1, playerName);
+ rs = prepStmt.executeQuery();
+
+ if (rs.next())
+ xPlayer = new xAuthPlayer(playerName, buildAccount(rs), buildSession(rs));
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not load player: " + playerName, e);
+ }
+
+ return xPlayer;
+ }
+
+ public void saveAccount(Account account) {
+ if (account.getId() == 0)
+ insertAccount(account);
+ else
+ updateAccount(account);
+ }
+
+ protected void insertAccount(Account account) {
+ try {
+ prepStmt = connection.prepareStatement(
+ "INSERT INTO `" + xAuthSettings.tblAccount + "`" +
+ " (`playername`, `password`, `email`, `registerdate`, `registerip`, `lastlogindate`, `lastloginip`, `active`)" +
+ " VALUES" +
+ " (?, ?, ?, ?, ?, ?, ?, ?)",
+ Statement.RETURN_GENERATED_KEYS);
+ prepStmt.setString(1, account.getPlayerName());
+ prepStmt.setString(2, account.getPassword());
+ prepStmt.setString(3, account.getEmail());
+ prepStmt.setTimestamp(4, account.getRegisterDate());
+ prepStmt.setString(5, account.getRegisterHost());
+ prepStmt.setTimestamp(6, account.getLastLoginDate());
+ prepStmt.setString(7, account.getLastLoginHost());
+ prepStmt.setInt(8, account.getActive());
+ prepStmt.executeUpdate();
+
+ rs = prepStmt.getGeneratedKeys();
+ if (rs.next())
+ account.setId(rs.getInt(1));
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not insert account for player: " + account.getPlayerName(), e);
+ }
+ }
+
+ public void insertAccounts(List accounts) {
+ StringBuilder sb = new StringBuilder();
+ Account account;
+ sb.append("INSERT INTO `" + xAuthSettings.tblAccount + "` (`playername`, `password`) VALUES");
+ sb.append(" (?, ?)");
+
+ for (int i = 1; i < accounts.size(); i++)
+ sb.append(", (?, ?)");
+ sb.append(";");
+
+ try {
+ prepStmt = connection.prepareStatement(sb.toString());
+ for (int i = 0, j = 1; j < accounts.size() * 2; i++, j += 2) {
+ account = accounts.get(i);
+ prepStmt.setString(j, account.getPlayerName());
+ prepStmt.setString(j + 1, account.getPassword().toLowerCase());
+ }
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected void updateAccount(Account account) {
+ try {
+ prepStmt = connection.prepareStatement(
+ "UPDATE `" + xAuthSettings.tblAccount + "`" +
+ " SET" +
+ " `playername` = ?," +
+ "`password` = ?," +
+ "`email` = ?," +
+ "`registerdate` = ?," +
+ "`registerip` = ?," +
+ "`lastlogindate` = ?," +
+ "`lastloginip` = ?," +
+ "`active` = ?" +
+ " WHERE id = ?"
+ );
+ prepStmt.setString(1, account.getPlayerName());
+ prepStmt.setString(2, account.getPassword());
+ prepStmt.setString(3, account.getEmail());
+ prepStmt.setTimestamp(4, account.getRegisterDate());
+ prepStmt.setString(5, account.getRegisterHost());
+ prepStmt.setTimestamp(6, account.getLastLoginDate());
+ prepStmt.setString(7, account.getLastLoginHost());
+ prepStmt.setInt(8, account.getActive());
+ prepStmt.setInt(9, account.getId());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not update account for player: " + account.getPlayerName(), e);
+ }
+ }
+
+ public void deleteAccount(xAuthPlayer xPlayer) {
+ Account account = xPlayer.getAccount();
+
+ try {
+ prepStmt = connection.prepareStatement(
+ "DELETE FROM `" + xAuthSettings.tblAccount + "`" +
+ " WHERE `id` = ?"
+ );
+ prepStmt.setInt(1, account.getId());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not delete account for player: " + xPlayer.getPlayerName(), e);
+ }
+
+ xPlayer.setAccount(null);
+ xPlayer.setSession(null);
+ }
+
+ public void insertSession(Session session) {
+ try {
+ prepStmt = connection.prepareStatement(
+ "INSERT INTO `" + xAuthSettings.tblSession + "`" +
+ " VALUES" +
+ " (?, ?, ?)",
+ Statement.RETURN_GENERATED_KEYS);
+ prepStmt.setInt(1, session.getAccountId());
+ prepStmt.setString(2, session.getHost());
+ prepStmt.setTimestamp(3, session.getLoginTime());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not insert session for account: " + session.getAccountId(), e);
+ }
+ }
+
+ public void deleteSession(xAuthPlayer xPlayer) {
+ Session session = xPlayer.getSession();
+
+ try {
+ prepStmt = connection.prepareStatement(
+ "DELETE FROM `" + xAuthSettings.tblSession + "`" +
+ " WHERE `accountid` = ?"
+ );
+ prepStmt.setInt(1, session.getAccountId());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not delete session for player: " + xPlayer.getPlayerName(), e);
+ }
+
+ xPlayer.setSession(null);
+ }
+
+ public void loadTeleLocations() {
+ //List teleLocations = new ArrayList();
+
+ try {
+ rs = stmt.executeQuery(
+ "SELECT * " +
+ "FROM `" + xAuthSettings.tblLocation + "`"
+ );
+
+ while (rs.next()) {
+ TeleLocation teleLocation = new TeleLocation();
+ teleLocation.setWorldName(rs.getString("worldname"));
+ teleLocation.setX(rs.getDouble("x"));
+ teleLocation.setY(rs.getDouble("y"));
+ teleLocation.setZ(rs.getDouble("z"));
+ teleLocation.setYaw(rs.getFloat("yaw"));
+ teleLocation.setPitch(rs.getFloat("pitch"));
+ teleLocations.put(teleLocation.getWorldName(), teleLocation);
+ //teleLocations.add(teleLocation);
+ }
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not load TeleLocations from database!", e);
+ }
+
+ //return teleLocations;
+ }
+
+ public void insertTeleLocation(TeleLocation teleLocation) {
+ try {
+ prepStmt = connection.prepareStatement(
+ "INSERT INTO `" + xAuthSettings.tblLocation + "`" +
+ " VALUES" +
+ " (?, ?, ?, ?, ?, ?)"
+ );
+
+ prepStmt.setString(1, teleLocation.getWorldName());
+ prepStmt.setDouble(2, teleLocation.getX());
+ prepStmt.setDouble(3, teleLocation.getY());
+ prepStmt.setDouble(4, teleLocation.getZ());
+ prepStmt.setFloat(5, teleLocation.getYaw());
+ prepStmt.setFloat(6, teleLocation.getPitch());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not insert TeleLocation for world: " + teleLocation.getWorldName(), e);
+ }
+ }
+
+ public void updateTeleLocation(TeleLocation teleLocation) {
+ try {
+ prepStmt = connection.prepareStatement(
+ "UPDATE `" + xAuthSettings.tblLocation + "`" +
+ " SET " +
+ "`x` = ?," +
+ "`y` = ?," +
+ "`z` = ?," +
+ "`yaw` = ?," +
+ "`pitch` = ?" +
+ " WHERE `worldname` = ?"
+ );
+ prepStmt.setDouble(1, teleLocation.getX());
+ prepStmt.setDouble(2, teleLocation.getY());
+ prepStmt.setDouble(3, teleLocation.getZ());
+ prepStmt.setFloat(4, teleLocation.getYaw());
+ prepStmt.setFloat(5, teleLocation.getPitch());
+ prepStmt.setString(6, teleLocation.getWorldName());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not update TeleLocation for world: " + teleLocation.getWorldName(), e);
+ }
+ }
+
+ public void deleteTeleLocation(TeleLocation teleLocation) {
+ try {
+ prepStmt = connection.prepareStatement(
+ "DELETE FROM `" + xAuthSettings.tblLocation + "`" +
+ " WHERE `worldname` = ?"
+ );
+
+ prepStmt.setString(1, teleLocation.getWorldName());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not delete TeleLocation for world: " + teleLocation.getWorldName(), e);
+ }
+ }
+
+ public StrikeBan loadStrikeBan(String host) {
+ StrikeBan ban = null;
+
+ try {
+ prepStmt = connection.prepareStatement(
+ "SELECT * " +
+ "FROM `" + xAuthSettings.tblStrike + "`" +
+ " WHERE `host` = ?"
+ );
+
+ prepStmt.setString(1, host);
+ rs = prepStmt.executeQuery();
+
+ if (rs.next()) {
+ ban = new StrikeBan();
+ ban.setHost(rs.getString("host"));
+ ban.setBanTime(rs.getTimestamp("bantime"));
+ }
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not load StrikeBan for host: " + host, e);
+ }
+
+ return ban;
+ }
+
+ public void insertStrikeBan(StrikeBan ban) {
+ try {
+ prepStmt = connection.prepareStatement(
+ "INSERT INTO `" + xAuthSettings.tblStrike + "`" +
+ " (`host`, `bantime`)" +
+ " VALUES" +
+ " (?, ?)"
+ );
+
+ prepStmt.setString(1, ban.getHost());
+ prepStmt.setTimestamp(2, ban.getBanTime());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not insert StrikeBan for host: " + ban.getHost(), e);
+ }
+ }
+
+ public void deleteStrikeBan(StrikeBan ban) {
+ try {
+ stmt = connection.prepareStatement(
+ "DELETE FROM `" + xAuthSettings.tblStrike + "`" +
+ " WHERE `host` = ?"
+ );
+
+ prepStmt.setString(1, ban.getHost());
+ prepStmt.executeUpdate();
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not delete StrikeBan for host: " + ban.getHost(), e);
+ }
+ }
+
+ public boolean isHostUsed(String host) {
+ try {
+ prepStmt = connection.prepareStatement(
+ "SELECT `id`" +
+ " FROM `" + xAuthSettings.tblAccount + "`" +
+ " WHERE `registerip` = ?"
+ );
+ prepStmt.setString(1, host);
+ rs = prepStmt.executeQuery();
+
+ if (rs.next())
+ return true;
+ } catch (SQLException e) {
+ xAuthLog.severe("Could not check if IP address has been used!", e);
+ }
+
+ return false;
+ }
+
+ public void close() {
+ try {
+ if (rs != null)
+ rs.close();
+ } catch (SQLException e) {}
+
+ try {
+ if (stmt != null)
+ stmt.close();
+ } catch (SQLException e) {}
+
+ try {
+ if (prepStmt != null)
+ prepStmt.close();
+ } catch (SQLException e) {}
+
+ try {
+ if (connection != null)
+ connection.close();
+ } catch (SQLException e) {}
+ }
+
+ private Account buildAccount(ResultSet rs) {
+ Account account = null;
+ try {
+ account = new Account();
+ account.setId(rs.getInt("id"));
+ account.setPlayerName(rs.getString("playername"));
+ account.setPassword(rs.getString("password"));
+ account.setEmail(rs.getString("email"));
+ account.setRegisterDate(rs.getTimestamp("registerdate"));
+ account.setRegisterHost(rs.getString("registerip"));
+ account.setLastLoginDate(rs.getTimestamp("lastlogindate"));
+ account.setLastLoginHost(rs.getString("lastloginip"));
+ account.setActive(rs.getInt("active"));
+ } catch (SQLException e) {
+ xAuthLog.severe("Error while building Account from ResultSet!", e);
+ }
+
+ return account;
+ }
+
+ private Session buildSession(ResultSet rs) {
+ Session session = null;
+ try {
+ session = new Session();
+ session.setAccountId(rs.getInt("accountid"));
+
+ if (rs.wasNull()) // no session data in database
+ return null;
+
+ session.setHost(rs.getString("host"));
+ session.setLoginTime(rs.getTimestamp("logintime"));
+ } catch (SQLException e) {
+ xAuthLog.severe("Error while building Session from ResultSet!", e);
+ }
+
+ return session;
+ }
+
+ public boolean isConnected() {
+ try {
+ if (connection == null || connection.isClosed())
+ return false;
+ } catch (SQLException e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public TeleLocation getTeleLocation(String worldName) {
+ return teleLocations.get(worldName);
+ }
+
+ public void setTeleLocation(TeleLocation teleLocation) {
+ TeleLocation tOld = teleLocations.put(teleLocation.getWorldName(), teleLocation);
+ if (tOld == null)
+ insertTeleLocation(teleLocation);
+ else
+ updateTeleLocation(teleLocation);
+ }
+
+ public void removeTeleLocation(TeleLocation teleLocation) {
+ teleLocations.remove(teleLocation.getWorldName());
+ deleteTeleLocation(teleLocation);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/listeners/xAuthBlockListener.java b/src/main/java/com/cypherx/xauth/listeners/xAuthBlockListener.java
new file mode 100644
index 0000000..a537ede
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/listeners/xAuthBlockListener.java
@@ -0,0 +1,58 @@
+package com.cypherx.xauth.listeners;
+
+import org.bukkit.event.Event;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockListener;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.plugin.PluginManager;
+
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthPlayer;
+
+public class xAuthBlockListener extends BlockListener {
+ private final xAuth plugin;
+
+ public xAuthBlockListener(xAuth plugin) {
+ this.plugin = plugin;
+ }
+
+ public void registerEvents() {
+ PluginManager pm = plugin.getServer().getPluginManager();
+ pm.registerEvent(Event.Type.BLOCK_BREAK, this, Event.Priority.Lowest, plugin);
+ pm.registerEvent(Event.Type.BLOCK_PLACE, this, Event.Priority.Lowest, plugin);
+ }
+
+ public void onBlockBreak(BlockBreakEvent event) {
+ if (event.isCancelled())
+ return;
+
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(event.getPlayer().getName());
+
+ //if (!xAuthSettings.rstrBreak && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest()) {
+ if (xPlayer.canNotify())
+ xPlayer.sendIllegalActionNotice();
+
+ event.setCancelled(true);
+ }
+ }
+
+ public void onBlockPlace(BlockPlaceEvent event) {
+ if (event.isCancelled())
+ return;
+
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(event.getPlayer().getName());
+
+ //if (!xAuthSettings.rstrPlace && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest()) {
+ if (xPlayer.canNotify())
+ xPlayer.sendIllegalActionNotice();
+
+ event.setCancelled(true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/listeners/xAuthEntityListener.java b/src/main/java/com/cypherx/xauth/listeners/xAuthEntityListener.java
new file mode 100644
index 0000000..c7ea63a
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/listeners/xAuthEntityListener.java
@@ -0,0 +1,79 @@
+package com.cypherx.xauth.listeners;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntityListener;
+import org.bukkit.event.entity.EntityTargetEvent;
+import org.bukkit.plugin.PluginManager;
+
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthPlayer;
+
+public class xAuthEntityListener extends EntityListener {
+ private final xAuth plugin;
+
+ public xAuthEntityListener(xAuth plugin) {
+ this.plugin = plugin;
+ }
+
+ public void registerEvents() {
+ PluginManager pm = plugin.getServer().getPluginManager();
+ pm.registerEvent(Event.Type.ENTITY_DAMAGE, this, Event.Priority.Lowest, plugin);
+ pm.registerEvent(Event.Type.ENTITY_TARGET, this, Event.Priority.Lowest, plugin);
+ }
+
+ public void onEntityDamage(EntityDamageEvent event) {
+ if (event.isCancelled())
+ return;
+
+ Entity entity = event.getEntity();
+ if (entity instanceof Player && ((Player)entity).isOnline()) { // player taking damage
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(((Player)entity).getName());
+
+ //if (!xAuthSettings.rstrDmgTaken && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest())
+ event.setCancelled(true);
+ else if (xPlayer.hasSession())
+ if (xPlayer.hasGodmode())
+ event.setCancelled(true);
+ } else if (event instanceof EntityDamageByEntityEvent) { // player dealing damage to other entity
+ EntityDamageByEntityEvent edbeEvent = (EntityDamageByEntityEvent)event;
+ Entity damager = edbeEvent.getDamager();
+
+ if (damager instanceof Player) {
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(((Player)entity).getName());
+
+ //if (!xAuthSettings.rstrDmgGiven && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest()) {
+ if (xPlayer.canNotify())
+ xPlayer.sendIllegalActionNotice();
+
+ event.setCancelled(true);
+ }
+ }
+ }
+ }
+
+ public void onEntityTarget(EntityTargetEvent event) {
+ if (event.isCancelled())
+ return;
+
+ Entity target = event.getTarget();
+ if (target instanceof Player) {
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(((Player)target).getName());
+
+ //if (!xAuthSettings.rstrMobTarget && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest())
+ event.setCancelled(true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/listeners/xAuthPlayerListener.java b/src/main/java/com/cypherx/xauth/listeners/xAuthPlayerListener.java
new file mode 100644
index 0000000..9996976
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/listeners/xAuthPlayerListener.java
@@ -0,0 +1,233 @@
+package com.cypherx.xauth.listeners;
+
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.player.*;
+import org.bukkit.event.player.PlayerLoginEvent.Result;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.PluginManager;
+
+import com.cypherx.xauth.Session;
+import com.cypherx.xauth.Util;
+import com.cypherx.xauth.xAuth;
+import com.cypherx.xauth.xAuthMessages;
+import com.cypherx.xauth.xAuthPlayer;
+import com.cypherx.xauth.xAuthSettings;
+
+public class xAuthPlayerListener extends PlayerListener {
+ private final xAuth plugin;
+
+ public xAuthPlayerListener(xAuth plugin) {
+ this.plugin = plugin;
+ }
+
+ public void registerEvents() {
+ PluginManager pm = plugin.getServer().getPluginManager();
+ pm.registerEvent(Event.Type.PLAYER_CHAT, this, Event.Priority.Lowest, plugin);
+ pm.registerEvent(Event.Type.PLAYER_COMMAND_PREPROCESS, this, Event.Priority.Lowest, plugin);
+ pm.registerEvent(Event.Type.PLAYER_INTERACT, this, Event.Priority.Lowest, plugin);
+ pm.registerEvent(Event.Type.PLAYER_JOIN, this, Event.Priority.Monitor, plugin);
+ pm.registerEvent(Event.Type.PLAYER_KICK, this, Event.Priority.Monitor, plugin);
+ pm.registerEvent(Event.Type.PLAYER_LOGIN, this, Event.Priority.Lowest, plugin);
+ pm.registerEvent(Event.Type.PLAYER_MOVE, this, Event.Priority.Lowest, plugin);
+ pm.registerEvent(Event.Type.PLAYER_PICKUP_ITEM, this, Event.Priority.Lowest, plugin);
+ pm.registerEvent(Event.Type.PLAYER_QUIT, this, Event.Priority.Monitor, plugin);
+ }
+
+ public void onPlayerLogin(PlayerLoginEvent event) {
+ if (!event.getResult().equals(Result.ALLOWED))
+ return;
+
+ String host = event.getKickMessage();
+ if (host != null && plugin.isBanned(host))
+ event.disallow(Result.KICK_OTHER, xAuthMessages.get("joinErrBanned", null, null));
+
+ Player player = event.getPlayer();
+ if (xAuthSettings.reverseESS && player.isOnline())
+ event.disallow(Result.KICK_OTHER, xAuthMessages.get("joinErrOnline", null, null));
+
+ if (!Util.isValidName(player))
+ event.disallow(Result.KICK_OTHER, xAuthMessages.get("joinErrName", null, null));
+ }
+
+ public void onPlayerJoin(PlayerJoinEvent event) {
+ final Player player = event.getPlayer();
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(player.getName());
+ boolean isRegistered = xPlayer.isRegistered();
+
+ if (!xPlayer.isAuthenticated() && (isRegistered || (!isRegistered && xPlayer.mustRegister()))) {
+ final String fieldName;
+ plugin.createGuest(xPlayer);
+
+ if (isRegistered)
+ fieldName = "joinLogin";
+ else
+ fieldName = "joinRegister";
+
+ // this is needed to send the message after the "xxx has joined.." announcement
+ plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, new Runnable() {
+ public void run() {
+ xAuthMessages.send(fieldName, player);
+ }
+ }, 1);
+ }
+ }
+
+ public void onPlayerKick(PlayerKickEvent event) {
+ // prevent WorldGuard from kicking the already online player
+ // if another with the same name joins
+ if (xAuthSettings.reverseESS) {
+ Plugin wgPlugin = plugin.getServer().getPluginManager().getPlugin("WorldGuard");
+
+ if (wgPlugin != null && event.getReason().equals("Logged in from another location."))
+ event.setCancelled(true);
+ }
+ }
+
+ public void onPlayerQuit(PlayerQuitEvent event) {
+ Player player = event.getPlayer();
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(player.getName());
+
+ if (xPlayer.isGuest())
+ plugin.removeGuest(xPlayer);
+ else if (xPlayer.hasSession()) {
+ Session session = xPlayer.getSession();
+ if (session.isExpired())
+ plugin.getDataManager().deleteSession(xPlayer);
+ }
+ }
+
+ public void onPlayerChat(PlayerChatEvent event) {
+ if (event.isCancelled())
+ return;
+
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(event.getPlayer().getName());
+
+ //if (!xAuthSettings.rstrChat && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest()) {
+ if (xPlayer.canNotify())
+ xPlayer.sendIllegalActionNotice();
+
+ event.setCancelled(true);
+ }
+ }
+
+ public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
+ if (event.isCancelled())
+ return;
+
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(event.getPlayer().getName());
+
+ //if (!xAuthSettings.rstrCommands && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest()) {
+ String command = event.getMessage().split(" ")[0];
+
+ if (!command.equals("/register") && !command.equals("/login") && !command.equals("/l")) {
+ if (xPlayer.canNotify())
+ xPlayer.sendIllegalActionNotice();
+
+ event.setMessage("");
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if (event.isCancelled())
+ return;
+
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(event.getPlayer().getName());
+
+ //if (!xAuthSettings.rstrInteract && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest()) {
+ Action action = event.getAction();
+ Material type = event.getClickedBlock().getType();
+
+ if (action == Action.LEFT_CLICK_BLOCK) {
+ if (type == Material.NOTE_BLOCK
+ //|| type == Material.TNT
+ || type == Material.WOODEN_DOOR
+ || type == Material.LEVER
+ || type == Material.IRON_DOOR
+ || type == Material.STONE_BUTTON
+ || type == Material.TRAP_DOOR) {
+ if (xPlayer.canNotify())
+ xPlayer.sendIllegalActionNotice();
+
+ event.setCancelled(true);
+ }
+ } else if (action == Action.RIGHT_CLICK_BLOCK) {
+ if (type == Material.DISPENSER
+ || type == Material.NOTE_BLOCK
+ || type == Material.BED
+ || type == Material.CHEST
+ || type == Material.WORKBENCH
+ || type == Material.FURNACE
+ || type == Material.SIGN
+ || type == Material.WOODEN_DOOR
+ || type == Material.LEVER
+ || type == Material.IRON_DOOR
+ || type == Material.STONE_BUTTON
+ || type == Material.JUKEBOX
+ || type == Material.TRAP_DOOR) {
+ if (xPlayer.canNotify())
+ xPlayer.sendIllegalActionNotice();
+
+ event.setCancelled(true);
+ }
+ } else if (action == Action.PHYSICAL) {
+ if (type == Material.SOIL || type == Material.STONE_PLATE || type == Material.WOOD_PLATE)
+ event.setCancelled(true);
+ }
+ }
+
+ /*xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(event.getPlayer().getName());
+ if (xPlayer.isGuest())
+ event.setCancelled(true);*/
+ }
+
+ public void onPlayerMove(PlayerMoveEvent event) {
+ if (event.isCancelled())
+ return;
+
+ Player player = event.getPlayer();
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(player.getName());
+
+ //if (!xAuthSettings.rstrMovement && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest()) {
+ Location loc = plugin.getLocationToTeleport(player.getWorld());
+ player.teleport(loc);
+ event.setFrom(loc);
+ event.setTo(loc);
+
+ if (xPlayer.canNotify())
+ xPlayer.sendIllegalActionNotice();
+
+ event.setCancelled(true);
+ }
+ }
+
+ public void onPlayerPickupItem(PlayerPickupItemEvent event) {
+ if (event.isCancelled())
+ return;
+
+ xAuthPlayer xPlayer = plugin.getDataManager().getPlayerByName(event.getPlayer().getName());
+
+ //if (!xAuthSettings.rstrPickup && !xPlayer.isRegistered())
+ //return;
+
+ if (xPlayer.isGuest())
+ event.setCancelled(true);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/xAuth.java b/src/main/java/com/cypherx/xauth/xAuth.java
new file mode 100644
index 0000000..8dd12c9
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/xAuth.java
@@ -0,0 +1,315 @@
+package com.cypherx.xauth;
+
+import com.cypherx.xauth.commands.*;
+import com.cypherx.xauth.datamanager.*;
+import com.cypherx.xauth.listeners.*;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.PlayerInventory;
+import org.bukkit.plugin.PluginDescriptionFile;
+import org.bukkit.plugin.java.JavaPlugin;
+//import org.bukkit.scheduler.BukkitTask;
+
+public class xAuth extends JavaPlugin {
+ public static PluginDescriptionFile desc;
+ public static File dataFolder;
+ private DataManager dataManager;
+
+ public void onDisable() {
+ Player[] players = getServer().getOnlinePlayers();
+ if (players.length > 0) {
+ for (Player player : players) {
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(player.getName());
+ if (xPlayer.isGuest())
+ removeGuest(xPlayer);
+ }
+ }
+
+ if (dataManager != null)
+ dataManager.close();
+
+ // not sure if necessary
+ /*Boolean activeTasks = true;
+ while (activeTasks) {
+ xAuthLog.info("Waiting for scheduled tasks to finish..");
+ for (BukkitTask task : getServer().getScheduler().getPendingTasks())
+ if (task.getOwner() == this)
+ continue;
+
+ activeTasks = false;
+ }*/
+
+ xAuthSettings.saveChanges();
+ xAuthLog.info("v" + desc.getVersion() + " Disabled!");
+ }
+
+ public void onEnable() {
+ desc = getDescription();
+ dataFolder = getDataFolder();
+
+ if (!dataFolder.exists())
+ dataFolder.mkdirs();
+
+ xAuthSettings.setup(dataFolder);
+ xAuthMessages.setup(dataFolder);
+
+ if (xAuthSettings.autoDisable && Util.getOnlineMode()) {
+ xAuthLog.warning("Disabling - Server is running in online-mode");
+ getServer().getPluginManager().disablePlugin(this);
+ return;
+ }
+
+ xAuthPermissions.setup(this);
+ xAuthHelp.setup(this);
+
+ dataManager = new DataManager();
+ if (!dataManager.isConnected()) {
+ xAuthLog.severe("Disabling - No connection to database");
+ getServer().getPluginManager().disablePlugin(this);
+ return;
+ }
+ dataManager.runStartupTasks();
+
+ File oldAuthFile = new File(dataFolder, "auths.txt");
+ if (oldAuthFile.exists())
+ importAccounts(oldAuthFile);
+
+ dataManager.printStats();
+
+ Player[] players = getServer().getOnlinePlayers();
+ if (players.length > 0) // /reload was used
+ handleReload(players);
+
+ (new xAuthPlayerListener(this)).registerEvents();
+ (new xAuthBlockListener(this)).registerEvents();
+ (new xAuthEntityListener(this)).registerEvents();
+ getCommand("register").setExecutor(new RegisterCommand(this));
+ getCommand("login").setExecutor(new LoginCommand(this));
+ getCommand("changepw").setExecutor(new ChangePasswordCommand(this));
+ getCommand("logout").setExecutor(new LogoutCommand(this));
+ getCommand("xauth").setExecutor(new xAuthCommand(this));
+
+ xAuthLog.info("v" + desc.getVersion() + " Enabled!");
+ }
+
+ private void importAccounts(File oldAuthFile) {
+ xAuthLog.info("Importing old auths.txt file to new format..");
+ List accounts = new ArrayList();
+ BufferedReader reader = null;
+
+ try {
+ reader = new BufferedReader(new FileReader(oldAuthFile));
+ String line;
+ Account account;
+
+ while ((line = reader.readLine()) != null) {
+ String[] split = line.split(":");
+ account = new Account(split[0], split[1], null);
+ accounts.add(account);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (reader != null)
+ reader.close();
+ } catch (IOException e) {}
+ }
+
+ dataManager.insertAccounts(accounts);
+
+ if (oldAuthFile.renameTo(new File(dataFolder, "auths.txt.old")))
+ xAuthLog.info("Import complete! auths.txt renamed to auths.txt.old");
+ else
+ xAuthLog.info("Import complete! Verify that all accounts were imported then remove/rename auths.txt");
+ }
+
+ private void handleReload(Player[] players) {
+ for (Player player : players) {
+ xAuthPlayer xPlayer = dataManager.getPlayerByName(player.getName());
+ boolean isRegistered = xPlayer.isRegistered();
+
+ if (!xPlayer.isAuthenticated() && (isRegistered || (!isRegistered && xPlayer.mustRegister()))) {
+ createGuest(xPlayer);
+ xAuthMessages.send("miscReloaded", player);
+ }
+ }
+ }
+
+ public void createGuest(xAuthPlayer xPlayer) {
+ final Player player = xPlayer.getPlayer();
+
+ // remove old session (if any)
+ if (xPlayer.hasSession())
+ dataManager.deleteSession(xPlayer);
+
+ if (xAuthSettings.guestTimeout > 0 && xPlayer.isRegistered()) {
+ int taskId = getServer().getScheduler().scheduleAsyncDelayedTask(this, new Runnable() {
+ public void run() {
+ player.kickPlayer(xAuthMessages.get("miscKickTimeout", player, null));
+ }
+ }, xAuthSettings.guestTimeout * 20);
+
+ xPlayer.setTimeoutTaskId(taskId);
+ }
+
+ protect(xPlayer);
+ xPlayer.setLastNotifyTime(Util.getNow());
+ xPlayer.setGuest(true);
+ }
+
+ public void removeGuest(xAuthPlayer xPlayer) {
+ getServer().getScheduler().cancelTask(xPlayer.getTimeoutTaskId());
+ restore(xPlayer);
+ xPlayer.setGuest(false);
+ }
+
+ public void protect(xAuthPlayer xPlayer) {
+ Player player = xPlayer.getPlayer();
+ PlayerInventory playerInv = player.getInventory();
+
+ xPlayer.setInventory(playerInv.getContents());
+ xPlayer.setArmor(playerInv.getArmorContents());
+ playerInv.clear();
+ playerInv.setHelmet(null);
+ playerInv.setChestplate(null);
+ playerInv.setLeggings(null);
+ playerInv.setBoots(null);
+ player.saveData();
+
+ if (player.getHealth() > 0)
+ xPlayer.setLocation(player.getLocation());
+
+ Location loc = getLocationToTeleport(player.getWorld());
+ player.teleport(loc);
+ }
+
+ public void restore(xAuthPlayer xPlayer) {
+ Player player = xPlayer.getPlayer();
+ PlayerInventory playerInv = player.getInventory();
+
+ ItemStack[] inv = xPlayer.getInventory();
+ //Backpack fix
+ if (playerInv.getSize() > inv.length) {
+ ItemStack[] newInv = new ItemStack[playerInv.getSize()];
+
+ for(int i = 0; i < inv.length; i++)
+ newInv[i] = inv[i];
+
+ inv = newInv;
+ }
+ //end Backpack fix
+
+ playerInv.setContents(inv);
+ playerInv.setArmorContents(xPlayer.getArmor());
+
+ if (xPlayer.getLocation() != null)
+ xPlayer.getPlayer().teleport(xPlayer.getLocation());
+ player.saveData();
+ }
+
+ public void login(xAuthPlayer xPlayer) {
+ Account account = xPlayer.getAccount();
+ account.setLastLoginDate(Util.getNow());
+ account.setLastLoginHost(Util.getHostFromPlayer(xPlayer.getPlayer()));
+ dataManager.saveAccount(account);
+
+ Session session = new Session(account.getId(), account.getLastLoginHost());
+ xPlayer.setSession(session);
+ dataManager.insertSession(session);
+
+ removeGuest(xPlayer);
+ }
+
+ public void changePassword(Account account, String newPass) {
+ account.setPassword(Util.encrypt(newPass));
+ dataManager.saveAccount(account);
+ }
+
+ public boolean checkPassword(Account account, String checkPass) {
+ String realPass = account.getPassword();
+
+ // check for old encryption (md5 or whirlpool)
+ if (realPass.length() == 32 || realPass.length() == 128) {
+ String hash = (realPass.length() == 32 ? Util.md5(checkPass) : Util.whirlpool(checkPass));
+ if (realPass.equals(hash)) {
+ changePassword(account, checkPass); // change password to use new encryption
+ return true;
+ } else
+ return false;
+ }
+
+ // xAuth 2 encryption
+ int saltPos = (checkPass.length() >= realPass.length() ? realPass.length() : checkPass.length());
+
+ // extract salt
+ String salt = realPass.substring(saltPos, saltPos + 8);
+
+ // encrypt salt + checkPass
+ Whirlpool w = new Whirlpool();
+ byte[] digest = new byte[Whirlpool.DIGESTBYTES];
+ w.NESSIEinit();
+ w.NESSIEadd(salt + checkPass);
+ w.NESSIEfinalize(digest);
+ String hash = Whirlpool.display(digest);
+ return (hash.substring(0, saltPos) + salt + hash.substring(saltPos)).equals(realPass);
+ }
+
+ public Location getLocationToTeleport(World world) {
+ TeleLocation teleLocation = dataManager.getTeleLocation(world.getName());
+ return (teleLocation == null ? world.getSpawnLocation() : teleLocation.getLocation());
+ }
+
+ public void strikeout(xAuthPlayer xPlayer) {
+ Player player = xPlayer.getPlayer();
+
+ if (xAuthSettings.strikeAction.equals("banip")) {
+ StrikeBan ban = new StrikeBan(Util.getHostFromPlayer(player));
+ getDataManager().insertStrikeBan(ban);
+ xAuthLog.info(ban.getHost() + " banned by strike system");
+ }
+
+ player.kickPlayer(xAuthMessages.get("miscKickStrike", player, null));
+ if (xAuthSettings.strikeAction.equals("kick"))
+ xAuthLog.info(player.getName() + " kicked by strike system");
+ }
+
+ public boolean isBanned(String host) {
+ final StrikeBan ban = dataManager.loadStrikeBan(host);
+ if (ban == null)
+ return false;
+
+ if (xAuthSettings.banLength == 0)
+ return true;
+
+ Timestamp unbanTime = new Timestamp(ban.getBanTime().getTime() + (xAuthSettings.banLength * 1000));
+ if (unbanTime.compareTo(Util.getNow()) > 0) // still banned
+ return true;
+ else // no longer banned, remove from database
+ dataManager.deleteStrikeBan(ban);
+
+ return false;
+ }
+
+ public void reload() {
+ xAuthSettings.setup(dataFolder);
+ xAuthMessages.setup(dataFolder);
+ //dataManager.close();
+ //dataManager = new DataManager();
+ }
+
+ public DataManager getDataManager() {
+ return dataManager;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/xAuthHelp.java b/src/main/java/com/cypherx/xauth/xAuthHelp.java
new file mode 100644
index 0000000..660de80
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/xAuthHelp.java
@@ -0,0 +1,28 @@
+package com.cypherx.xauth;
+
+import me.taylorkelly.help.Help;
+import org.bukkit.plugin.Plugin;
+
+public class xAuthHelp {
+ public static void setup(xAuth plugin) {
+ Plugin test = plugin.getServer().getPluginManager().getPlugin("Help");
+ if (test != null) {
+ Help helpPlugin = ((Help) test);
+ String[] permissions = new String[]{"xauth.admin.register", "xauth.admin.changepw", "xauth.admin.logout", "xauth.admin.unregister", "xauth.admin.location", "xauth.admin.config", "xauth.admin.reload"};
+ helpPlugin.registerCommand("register [password] (email)", "Create an in-game account linked to your player name", plugin, true);
+ helpPlugin.registerCommand("login [password]", "Authenticate yourself as the account owner", plugin, true);
+ helpPlugin.registerCommand("changepw [old password] [new password]", "Change your password", plugin);
+ helpPlugin.registerCommand("logout", "Terminate your session", plugin);
+ helpPlugin.registerCommand("xauth register [player] [password] (email)", "Create an account for [player]", plugin, permissions[0]);
+ helpPlugin.registerCommand("xauth changepw [player] [new password]", "Change [player]'s password to [new password]", plugin, permissions[1]);
+ helpPlugin.registerCommand("xauth logout [player]", "Terminate [player]'s session", plugin, permissions[2]);
+ helpPlugin.registerCommand("xauth unregister [player]", "Remove [player]'s account", plugin, permissions[3]);
+ helpPlugin.registerCommand("xauth location set", "Set your current location as this worlds teleport location", plugin, permissions[4]);
+ helpPlugin.registerCommand("xauth location remove", "Remove this worlds teleport location", plugin, permissions[4]);
+ helpPlugin.registerCommand("xauth config [setting] (new value)", "View info about or change a setting", plugin, permissions[5]);
+ helpPlugin.registerCommand("xauth reload", "Reload the xAuth configuration and accounts", plugin, permissions[6]);
+ xAuthLog.info("'Help' support enabled");
+ } else
+ xAuthLog.warning("'Help' isn't detected. No /help support");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/xAuthLog.java b/src/main/java/com/cypherx/xauth/xAuthLog.java
new file mode 100644
index 0000000..2718179
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/xAuthLog.java
@@ -0,0 +1,32 @@
+package com.cypherx.xauth;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class xAuthLog {
+ private static final Logger logger = Logger.getLogger("Minecraft");
+
+ public static void info(String msg) {
+ logger.log(Level.INFO, "[xAuth] " + msg);
+ }
+
+ public static void warning(String msg) {
+ logger.log(Level.WARNING, "[xAuth] " + msg);
+ }
+
+ public static void severe(String msg) {
+ logger.log(Level.SEVERE, "[xAuth] " + msg);
+ }
+
+ public static void info(String msg, Throwable e) {
+ logger.log(Level.INFO, "[xAuth] " + msg, e);
+ }
+
+ public static void warning(String msg, Throwable e) {
+ logger.log(Level.WARNING, "[xAuth] " + msg, e);
+ }
+
+ public static void severe(String msg, Throwable e) {
+ logger.log(Level.SEVERE, "[xAuth] " + msg, e);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/xAuthMessages.java b/src/main/java/com/cypherx/xauth/xAuthMessages.java
new file mode 100644
index 0000000..ddee814
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/xAuthMessages.java
@@ -0,0 +1,274 @@
+package com.cypherx.xauth;
+
+import java.io.File;
+
+import org.bukkit.entity.Player;
+import org.bukkit.util.config.Configuration;
+
+public class xAuthMessages {
+ private static File file;
+ private static Configuration config;
+
+ // join
+ public static String joinRegister = "{RED}You are not registered.{NEWLINE}{RED}Please register using /register .";
+ public static String joinLogin = "{RED}Please log in using /login .";
+ public static String joinErrBanned = "You have are banned for exceeding the incorrect password threshold.";
+ public static String joinErrOnline = "You are already online!";
+ public static String joinErrName = "Your name contains one or more illegal characters.";
+
+ // register
+ public static String regUsage = "{RED}Correct Usage: /register [email]";
+ public static String regSuccess = "{BRIGHTGREEN}You have successfully registered!";
+ public static String regErrDisabled = "{RED}Registrations are currently disabled!";
+ public static String regErrRegistered = "{RED}You are already registered!";
+ public static String regErrMultiple = "{RED}You may only register one account!";
+ public static String regErrPassword = "{RED}Your password must be at least {PWMINLENGTH} characters long!";
+ public static String regErrEmail = "{RED}Please use a valid email address when registering!";
+
+ // login
+ public static String loginUsage = "{RED}Correct Usage: /login ";
+ public static String loginSuccess = "{BRIGHTGREEN}You are now logged in!";
+ public static String loginErrRegistered = "{RED}You are not registered!";
+ public static String loginErrLogged = "{RED}You are already logged in!";
+ public static String loginErrPassword = "{RED}Incorrect password!";
+ public static String loginErrActivate = "{RED}Your account is not activated!";
+
+ // logout
+ public static String logoutSuccess = "{BRIGHTGREEN}You have been logged out!";
+ public static String logoutErrLogged = "{RED}You are not logged in!";
+
+ // change password
+ public static String cpwUsage = "{RED}Correct Usage: /changepw ";
+ public static String cpwSuccess = "{BRIGHTGREEN}Password changed!";
+ public static String cpwErrDisabled = "{RED}Password changes are currently disabled!";
+ public static String cpwErrLogged = "{RED}You are not logged in!";
+ public static String cpwErrIncorrect = "{RED}Incorrect old password!";
+ public static String cpwErrInvalid = "{RED}Your new password must be at least {PWMINLENGTH} characters long!";
+
+ // admin
+ public static String admnUnknown = "Unknown subcommand, try /xauth for more information";
+ public static String admnPermission = "You do not have permission to use this command!";
+ public static String admnRegUsage = "{RED}Correct Usage: /xauth register [email]";
+ public static String admnRegRegistered = "{RED}This player is already registered!";
+ public static String admnRegSuccess = "{BRIGHTGREEN}Account successfully created for: {WHITE}{TARGET}";
+ public static String admnCpwUsage = "{RED}Correct Usage: /xauth changepw ";
+ public static String admnCpwRegistered = "{RED}This player is not registered!";
+ public static String admnCpwSuccess = "{TARGET}''s {BRIGHTGREEN}password has been changed!";
+ public static String admnLogoutUsage = "{RED}Correct Usage: /xauth logout ";
+ public static String admnLogoutLogged = "{TARGET} {RED}is not logged in!";
+ public static String admnLogoutSuccess = "{TARGET} {BRIGHTGREEN}has been logged out!";
+ public static String admnUnregUsage = "{RED}Correct Usage: /xauth unregister ";
+ public static String admnUnregRegistered = "{RED}This player is not registered!";
+ public static String admnUnregSuccessTgt = "{RED}You have been unregistered and logged out!";
+ public static String admnUnregSuccessPlyr = "{TARGET} {BRIGHTGREEN}has been unregistered!";
+ public static String admnLocUsage = "{RED}Correct Usage: /xauth location set|remove";
+ public static String admnLocSetSuccess = "{YELLOW}{PLUGIN} {BRIGHTGREEN}Teleport location for this world set to your location!";
+ public static String admnLocRmvNo = "{YELLOW}{PLUGIN} {BRIGHTGREEN}This world does not have a teleport location!";
+ public static String admnLocRmvSuccess = "{YELLOW}{PLUGIN} {BRIGHTGREEN}Teleport location for this world has been removed!";
+ public static String admnConfUsage = "{RED}Correct Usage: /xauth config [new value]";
+ public static String admnConfNo = "{YELLOW}{PLUGIN} {RED}No such setting!";
+ public static String admnConfDesc = "Setting: {SETTING}{NEWLINE}Type: {TYPE}{NEWLINE}Value: {VALUE}";
+ public static String admnConfInvalid = "{RED}Invalid value type!";
+ public static String admnConfSuccess = "{YELLOW}{PLUGIN} {BRIGHTGREEN}Setting changed!";
+ public static String admnReloadSuccess = "{YELLOW}{PLUGIN} {BRIGHTGREEN}Reload complete!";
+
+ // misc
+ public static String miscIllegal = "{GRAY}You must be logged in to do that!";
+ public static String miscKickTimeout = "You have taken too long to log in!";
+ public static String miscKickStrike = "You have entered too many invalid passwords!";
+ public static String miscReloaded = "{RED}Server reloaded, please log in.";
+
+ /*
+ * REMEMBER TO CHANGE VERSION AFTER MODIFYING DEFAULT STRINGS
+ */
+ public static int version = 1;
+
+ public static void setup(File dataFolder) {
+ file = new File(dataFolder, "messages.yml");
+
+ if (!file.exists()) {
+ xAuthLog.info("Creating file: messages.yml");
+ Util.writeConfig(file, xAuthMessages.class);
+ } else {
+ config = new Configuration(file);
+ config.load();
+ loadMessages();
+ update();
+ }
+ }
+
+ public static void loadMessages() {
+ joinRegister = getString("join.register", joinRegister);
+ joinLogin = getString("join.login", joinLogin);
+ joinErrBanned = getString("join.error.banned", joinErrBanned);
+ joinErrOnline = getString("join.error.online", joinErrOnline);
+ joinErrName = getString("join.error.name", joinErrOnline);
+
+ regUsage = getString("register.usage", regUsage);
+ regSuccess = getString("register.success", regSuccess);
+ regErrDisabled = getString("register.error.disable", regErrDisabled);
+ regErrRegistered = getString("register.error.registered", regErrRegistered);
+ regErrMultiple = getString("register.error.multiple", regErrMultiple);
+ regErrPassword = getString("register.error.password", regErrPassword);
+ regErrEmail = getString("register.error.email", regErrEmail);
+
+ loginUsage = getString("login.usage", loginUsage);
+ loginSuccess = getString("login.success", loginSuccess);
+ loginErrRegistered = getString("login.error.registered", loginErrRegistered);
+ loginErrLogged = getString("login.error.logged", loginErrLogged);
+ loginErrPassword = getString("login.error.password", loginErrPassword);
+ loginErrActivate = getString("login.error.activate", loginErrActivate);
+
+ logoutSuccess = getString("logout.success", logoutSuccess);
+ logoutErrLogged = getString("logout.error.logged", logoutErrLogged);
+
+ cpwUsage = getString("changepw.usage", cpwUsage);
+ cpwSuccess = getString("changepw.success", cpwSuccess);
+ cpwErrDisabled = getString("changepw.error.disabled", cpwErrDisabled);
+ cpwErrLogged = getString("changepw.error.logged", cpwErrLogged);
+ cpwErrIncorrect = getString("changepw.error.incorrect", cpwErrIncorrect);
+ cpwErrInvalid = getString("changepw.error.invalid", cpwErrInvalid);
+
+ admnUnknown = getString("admin.unknown", admnUnknown);
+ admnPermission = getString("admin.permission", admnPermission);
+ admnRegUsage = getString("admin.register.usage", admnRegUsage);
+ admnRegRegistered = getString("admin.register.registered", admnRegRegistered);
+ admnRegSuccess = getString("admin.register.success", admnRegSuccess);
+ admnCpwUsage = getString("admin.changepw.usage", admnCpwUsage);
+ admnCpwRegistered = getString("admin.changepw.registered", admnCpwRegistered);
+ admnCpwSuccess = getString("admin.changepw.success", admnCpwSuccess);
+ admnLogoutUsage = getString("admin.logout.usage", admnLogoutUsage);
+ admnLogoutLogged = getString("admin.logout.logged", admnLogoutLogged);
+ admnLogoutSuccess = getString("admin.logout.success", admnLogoutSuccess);
+ admnUnregUsage = getString("admin.unregister.usage", admnUnregUsage);
+ admnUnregRegistered = getString("admin.unregister.registered", admnUnregRegistered);
+ admnUnregSuccessTgt = getString("admin.unregister.success.target", admnUnregSuccessTgt);
+ admnUnregSuccessPlyr = getString("admin.unregister.success.player", admnUnregSuccessPlyr);
+ admnLocUsage = getString("admin.location.usage", admnLocUsage);
+ admnLocSetSuccess = getString("admin.location.set.success", admnLocSetSuccess);
+ admnLocRmvNo = getString("admin.location.remove.no", admnLocRmvNo);
+ admnLocRmvSuccess = getString("admin.location.remove.success", admnLocRmvSuccess);
+ admnConfUsage = getString("admin.config.usage", admnConfUsage);
+ admnConfNo = getString("admin.config.no", admnConfNo);
+ admnConfDesc = getString("admin.config.desc", admnConfDesc);
+ admnConfInvalid = getString("admin.config.invalid", admnConfInvalid);
+ admnConfSuccess = getString("admin.config.success", admnConfSuccess);
+ admnReloadSuccess = getString("admin.reload.success", admnReloadSuccess);
+
+ miscIllegal = getString("misc.illegal", miscIllegal);
+ miscKickTimeout = getString("misc.kick.timeout", miscKickTimeout);
+ miscKickStrike = getString("misc.kick.strike", miscKickStrike);
+ miscReloaded = getString("misc.reloaded", miscReloaded);
+ }
+
+ private static String getString(String key, String def) {
+ return config.getString(key, def);
+ }
+
+ private static int getInt(String key, int def) {
+ return config.getInt(key, def);
+ }
+
+ private static void update() {
+ if (version > getInt("version", version)) {
+ xAuthLog.info("Updating file: messages.yml");
+ Util.writeConfig(file, xAuthSettings.class);
+ }
+ }
+
+ public static void send(String fieldName, Player player) {
+ String message = get(fieldName, player, null);
+
+ for (String line : message.split("\n"))
+ player.sendMessage(line);
+ }
+
+ public static void send(String fieldName, Player player, Player target) {
+ String message = get(fieldName, player, target);
+
+ for (String line : message.split("\n"))
+ player.sendMessage(line);
+ }
+
+ public static String get(String fieldName, Player player, Player target) {
+ String message = null;
+ try {
+ message = xAuthMessages.class.getField(fieldName).get(null).toString();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ return replace(message, player, target);
+ }
+
+ private static String replace(String message, Player player, Player target) {
+ // colors
+ message = message.replace("{BLACK}", "&0");
+ message = message.replace("{DARKBLUE}", "&1");
+ message = message.replace("{DARKGREEN}", "&2");
+ message = message.replace("{DARKTEAL}", "&3");
+ message = message.replace("{DARKRED}", "&4");
+ message = message.replace("{PURPLE}", "&5");
+ message = message.replace("{GOLD}", "&6");
+ message = message.replace("{GRAY}", "&7");
+ message = message.replace("{DARKGRAY}", "&8");
+ message = message.replace("{BLUE}", "&9");
+ message = message.replace("{BRIGHTGREEN}", "&a");
+ message = message.replace("{TEAL}", "&b");
+ message = message.replace("{RED}", "&c");
+ message = message.replace("{PINK}", "&d");
+ message = message.replace("{YELLOW}", "&e");
+ message = message.replace("{WHITE}", "&f");
+ message = message.replace("&", "\u00a7");
+
+
+ // plugin
+ message = message.replace("{PLUGIN}", "[" + xAuth.desc.getName() + "]");
+ message = message.replace("{VERSION}", xAuth.desc.getVersion());
+
+ // player
+ if (player != null) {
+ message = message.replace("{PLAYER}", player.getName());
+ message = message.replace("{IP}", Util.getHostFromPlayer(player));
+ }
+
+ // target
+ if (target != null) {
+ message = message.replace("{TARGET}", player.getName());
+ message = message.replace("{TARGETIP}", Util.getHostFromPlayer(player));
+ }
+
+ // settings
+ message = message.replace("{PWMINLENGTH}", Integer.toString(xAuthSettings.pwMinLength));
+
+ // misc
+ message = message.replace("{NEWLINE}", "\n");
+
+ return message;
+ }
+
+ // separate method for this because I'm lazy
+ public static void sendConfigDesc(Player player, String setting, String type, Object value) {
+ String message = null;
+ try {
+ message = xAuthMessages.class.getField("admnConfDesc").get(null).toString();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+
+ if (message == null)
+ return;
+
+ message = message.replace("{SETTING}", setting);
+ message = message.replace("{TYPE}", type);
+ message = message.replace("{VALUE}", value.toString());
+ message = message.replace("{NEWLINE}", "\n");
+
+ for (String line : message.split("\n"))
+ player.sendMessage(line);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/xAuthPermissions.java b/src/main/java/com/cypherx/xauth/xAuthPermissions.java
new file mode 100644
index 0000000..493b150
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/xAuthPermissions.java
@@ -0,0 +1,30 @@
+package com.cypherx.xauth;
+
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+
+import com.nijiko.permissions.PermissionHandler;
+import com.nijikokun.bukkit.Permissions.Permissions;
+
+public class xAuthPermissions {
+ private static PermissionHandler permissionHandler;
+
+ public static void setup(xAuth plugin) {
+ Plugin permissionsPlugin = plugin.getServer().getPluginManager().getPlugin("Permissions");
+
+ if (permissionHandler == null) {
+ if (permissionsPlugin != null) {
+ permissionHandler = ((Permissions) permissionsPlugin).getHandler();
+ xAuthLog.info("'Permission' support enabled");
+ } else
+ xAuthLog.warning("Permission system not detected, defaulting to OP");
+ }
+ }
+
+ public static boolean has(Player player, String permission) {
+ if (permissionHandler == null)
+ return player.isOp();
+
+ return permissionHandler.has(player, permission);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/xAuthPlayer.java b/src/main/java/com/cypherx/xauth/xAuthPlayer.java
new file mode 100644
index 0000000..ec81ce9
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/xAuthPlayer.java
@@ -0,0 +1,169 @@
+package com.cypherx.xauth;
+
+import java.sql.Timestamp;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+public class xAuthPlayer {
+ private String playerName;
+ private Account account;
+ private Session session;
+ private boolean guest = false;
+ private Location location;
+ private ItemStack[] inventory;
+ private ItemStack[] armor;
+ private Timestamp lastNotifyTime;
+ private int strikes = 0;
+ private int timeoutTaskId;
+
+ public xAuthPlayer(String playerName) {
+ this.playerName = playerName;
+ }
+
+ public xAuthPlayer(String playerName, Account account, Session session) {
+ this.playerName = playerName;
+ this.account = account;
+
+ if (session != null)
+ this.session = session;
+ }
+
+ public boolean isRegistered() {
+ return (account != null);
+ }
+
+ public boolean hasSession() {
+ return (session != null);
+ }
+
+ public boolean isAuthenticated() {
+ if (session == null)
+ return false;
+
+ if (session.isExpired() || !session.getHost().equals(Util.getHostFromPlayer(getPlayer())))
+ return false;
+
+ return true;
+ }
+
+ public boolean mustRegister() {
+ if (xAuthSettings.regForced)
+ return true;
+
+ return xAuthPermissions.has(getPlayer(), "xauth.register");
+ }
+
+ public boolean canNotify() {
+ if (lastNotifyTime == null)
+ return true;
+
+ Timestamp nextNotifyTime = new Timestamp(lastNotifyTime.getTime() + (xAuthSettings.notifyCooldown * 1000));
+ if (nextNotifyTime.compareTo(Util.getNow()) < 0)
+ return true;
+
+ return false;
+ }
+
+ public void sendIllegalActionNotice() {
+ xAuthMessages.send("miscIllegal", getPlayer());
+ lastNotifyTime = Util.getNow();
+ }
+
+ public boolean hasGodmode() {
+ if (xAuthSettings.godmodeLength < 1)
+ return false;
+
+ Timestamp expireTime = new Timestamp(session.getLoginTime().getTime() + (xAuthSettings.godmodeLength * 1000));
+ if (expireTime.compareTo(Util.getNow()) < 0)
+ return false;
+
+ return true;
+ }
+
+ public void setPlayerName(String playerName) {
+ this.playerName = playerName;
+ }
+
+ public String getPlayerName() {
+ return playerName;
+ }
+
+ public Player getPlayer() {
+ return Bukkit.getServer().getPlayer(playerName);
+ }
+
+ public void setAccount(Account account) {
+ this.account = account;
+ }
+
+ public Account getAccount() {
+ return account;
+ }
+
+ public void setSession(Session session) {
+ this.session = session;
+ }
+
+ public Session getSession() {
+ return session;
+ }
+
+ public void setGuest(boolean guest) {
+ this.guest = guest;
+ }
+
+ public boolean isGuest() {
+ return guest;
+ }
+
+ public void setLocation(Location location) {
+ this.location = location;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public void setInventory(ItemStack[] inventory) {
+ this.inventory = inventory;
+ }
+
+ public ItemStack[] getInventory() {
+ return inventory;
+ }
+
+ public void setArmor(ItemStack[] armor) {
+ this.armor = armor;
+ }
+
+ public ItemStack[] getArmor() {
+ return armor;
+ }
+
+ public void setLastNotifyTime(Timestamp lastNotifyTime) {
+ this.lastNotifyTime = lastNotifyTime;
+ }
+
+ public Timestamp getLastNotifyTime() {
+ return lastNotifyTime;
+ }
+
+ public void setStrikes(int strikes) {
+ this.strikes = strikes;
+ }
+
+ public int getStrikes() {
+ return strikes;
+ }
+
+ public void setTimeoutTaskId(int timeoutTaskId) {
+ this.timeoutTaskId = timeoutTaskId;
+ }
+
+ public int getTimeoutTaskId() {
+ return timeoutTaskId;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/cypherx/xauth/xAuthSettings.java b/src/main/java/com/cypherx/xauth/xAuthSettings.java
new file mode 100644
index 0000000..0fb70d0
--- /dev/null
+++ b/src/main/java/com/cypherx/xauth/xAuthSettings.java
@@ -0,0 +1,193 @@
+package com.cypherx.xauth;
+
+import java.io.File;
+
+import org.bukkit.util.config.Configuration;
+
+public class xAuthSettings {
+ private static File file;
+ private static Configuration config;
+ public static boolean changed = false;
+
+ // main
+ public static String datasource = "default";
+ public static boolean autoDisable = true;
+ public static boolean reverseESS = true;
+
+ // mysql
+ public static String mysqlHost = "localhost";
+ public static int mysqlPort = 3306;
+ public static String mysqlUser = "root";
+ public static String mysqlPass = "";
+ public static String mysqlDb = "";
+ public static String tblAccount = "accounts";
+ public static String tblSession = "sessions";
+ public static String tblStrike = "strike_bans";
+ public static String tblLocation = "tele_locations";
+ /*public static String colAccId = "id";
+ public static String colAccPlayerName = "playername";
+ public static String colAccPassword = "password";
+ public static String colAccEmail = "email";
+ public static String colAccRegDate = "registerdate";
+ public static String colAccRegIp = "registerip";
+ public static String colAccLastLoginDate = "lastlogindate";
+ public static String colAccLastLoginIp = "lastloginip";
+ public static String colAccActive = "active";*/
+
+ // registration
+ public static boolean regEnabled = true;
+ public static boolean regForced = true;
+ public static boolean requireEmail = false;
+ public static boolean validateEmail = true;
+ public static boolean allowMultiple = true;
+ public static boolean activation = false;
+
+ // login
+ public static int maxStrikes = 5;
+ public static String strikeAction = "kick";
+ public static int banLength = 3600;
+
+ // password
+ public static int pwMinLength = 6;
+ public static boolean pwAllowChange = true;
+ public static boolean pwCompLower = false;
+ public static boolean pwCompUpper = false;
+ public static boolean pwCompNumber = false;
+ public static boolean pwCompSymbol = false;
+
+ // guest
+ public static int guestTimeout = 300;
+ public static int notifyCooldown = 5;
+
+ // session
+ public static int sessionLength = 3600;
+ public static boolean verifyIp = true;
+ public static int godmodeLength = 5;
+
+ // filter
+ public static int filterMinLength = 2;
+ public static String filterAllowed = "*";
+ public static boolean filterBlank = true;
+
+ // restrictions
+ /*public static boolean rstrChat = true;
+ public static boolean rstrCommands = true;
+ public static boolean rstrInteract = true;
+ public static boolean rstrMovement = true;
+ public static boolean rstrPickup = true;
+ public static boolean rstrBreak = true;
+ public static boolean rstrPlace = true;
+ public static boolean rstrDmgTaken = true;
+ public static boolean rstrDmgGiven = true;
+ public static boolean rstrMobTarget = true;*/
+
+ /*
+ * REMEMBER TO CHANGE VERSION AFTER MODIFYING DEFAULT SETTINGS
+ */
+ public static int version = 1;
+
+ public static void setup(File dataFolder) {
+ file = new File(dataFolder, "config.yml");
+
+ if (!file.exists()) {
+ xAuthLog.info("Creating file: config.yml");
+ Util.writeConfig(file, xAuthSettings.class);
+ } else {
+ config = new Configuration(file);
+ config.load();
+ loadSettings();
+ update();
+ }
+ }
+
+ public static void loadSettings() {
+ datasource = getString("main.datasource", datasource);
+ autoDisable = getBool("main.auto-disable", autoDisable);
+ reverseESS = getBool("main.reverse-enforce-single-session", reverseESS);
+
+ mysqlHost = getString("mysql.host", mysqlHost);
+ mysqlPort = getInt("mysql.port", mysqlPort);
+ mysqlUser = getString("mysql.username", mysqlUser);
+ mysqlPass = getString("mysql.password", mysqlPass);
+ mysqlDb = getString("mysql.database", mysqlDb);
+ tblAccount = getString("mysql.tables.account", tblAccount);
+ tblSession = getString("mysql.tables.session", tblSession);
+ tblStrike = getString("mysql.tables.strike", tblStrike);
+ tblLocation = getString("mysql.tables.location", tblLocation);
+ /*colAccId = getString("mysql.columns.account.id", colAccId);
+ colAccPlayerName = getString("mysql.columns.account.playername", colAccPlayerName);
+ colAccPassword = getString("mysql.columns.account.password", colAccPassword);
+ colAccEmail = getString("mysql.columns.account.email", colAccEmail);
+ colAccRegDate = getString("mysql.columns.account.registerdate", colAccRegDate);
+ colAccRegIp = getString("mysql.columns.account.registerip", colAccRegIp);
+ colAccLastLoginDate = getString("mysql.columns.account.lastlogindate", colAccLastLoginDate);
+ colAccLastLoginIp = getString("mysql.columns.account.lastloginip", colAccLastLoginIp);
+ colAccActive = getString("mysql.columns.account.active", colAccActive);*/
+
+ regEnabled = getBool("registration.enabled", regEnabled);
+ regForced = getBool("registration.forced", regForced);
+ requireEmail = getBool("registration.require-email", requireEmail);
+ validateEmail = getBool("registration.validate-email", validateEmail);
+ allowMultiple = getBool("registration.allow-multiple", allowMultiple);
+ activation = getBool("registration.activation", activation);
+
+ maxStrikes = getInt("login.strikes.amount", maxStrikes);
+ strikeAction = getString("login.strikes.action", strikeAction);
+ banLength = getInt("login.strikes.length", banLength);
+
+ pwMinLength = getInt("password.min-length", pwMinLength);
+ pwAllowChange = getBool("password.allow-change", pwAllowChange);
+ pwCompLower = getBool("password.complexity.lowercase", pwCompLower);
+ pwCompUpper = getBool("password.complexity.uppercase", pwCompUpper);
+ pwCompNumber = getBool("password.complexity.number", pwCompNumber);
+ pwCompSymbol = getBool("password.complexity.symbol", pwCompSymbol);
+
+ guestTimeout = getInt("guest.timeout", guestTimeout);
+ notifyCooldown = getInt("guest.notify-cooldown", notifyCooldown);
+
+ sessionLength = getInt("session.length", sessionLength);
+ verifyIp = getBool("session.verifyip", verifyIp);
+ godmodeLength = getInt("session.godmode-length", godmodeLength);
+
+ filterMinLength = getInt("filter.min-length", filterMinLength);
+ filterAllowed = getString("filter.allowed", filterAllowed);
+ filterBlank = getBool("filter.blankname", filterBlank);
+
+ /*rstrChat = getBool("restrict.chat", rstrChat);
+ rstrCommands = getBool("restrict.commands", rstrCommands);
+ rstrInteract = getBool("restrict.interact", rstrInteract);
+ rstrMovement = getBool("restrict.movement", rstrMovement);
+ rstrPickup = getBool("restrict.item-pickup", rstrPickup);
+ rstrBreak = getBool("restrict.block-break", rstrBreak);
+ rstrPlace = getBool("restrict.block-place", rstrPlace);
+ rstrDmgTaken = getBool("restrict.damage-taken", rstrDmgTaken);
+ rstrDmgGiven = getBool("restrict.damage-given", rstrDmgGiven);
+ rstrMobTarget = getBool("restrict.mob-target", rstrMobTarget);*/
+ }
+
+ private static String getString(String key, String def) {
+ return config.getString(key, def);
+ }
+
+ private static int getInt(String key, int def) {
+ return config.getInt(key, def);
+ }
+
+ private static boolean getBool(String key, boolean def) {
+ return config.getBoolean(key, def);
+ }
+
+ private static void update() {
+ if (version > getInt("version", version)) {
+ xAuthLog.info("Updating file: config.yml");
+ Util.writeConfig(file, xAuthSettings.class);
+ }
+ }
+
+ public static void saveChanges() {
+ if (changed) {
+ xAuthLog.info("Saving configuration changes..");
+ Util.writeConfig(file, xAuthSettings.class);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/MANIFEST.MF b/src/main/resources/MANIFEST.MF
new file mode 100644
index 0000000..cbde614
--- /dev/null
+++ b/src/main/resources/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Class-Path: ../lib/h2.jar
\ No newline at end of file
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..1654920
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1,96 @@
+#
+# Configuration file for xAuth
+#
+
+main:
+ # How should xAuth store data (Accounts, sessions, etc.)?
+ # Possible values: default (H2), mysql
+ datasource: [datasource]
+ # If set to true, xAuth will disable itself if the server is in online-mode
+ auto-disable: [autoDisable]
+ # When set to true, if a player connects with the same name as someone who is
+ # already online, the player connecting will be kicked instead of the online player
+ reverse-enforce-single-session: true
+
+mysql:
+ # Location of the MySQL server. Can be either a host name or IP address
+ host: [mysqlHost]
+ # Port used by MySQL. Default is 3306
+ port: [mysqlPort]
+ # User name used to connect to the MySQL server
+ username: [mysqlUser]
+ # Password used to connect to the MySQL server
+ password: [mysqlPass]
+ # Name of the database that will be used by xAuth
+ database: [mysqlDb]
+ # Names of the tables xAuth will use to store data
+ tables:
+ account: [tblAccount]
+ session: [tblSession]
+ strike: [tblStrike]
+ location: [tblLocation]
+
+registration:
+ # Enable/disable new registrations
+ enabled: [regEnabled]
+ # If set to true, everyone must register
+ forced: [regForced]
+ # Setting this to true requires a player to enter an email address when they register
+ require-email: [requireEmail]
+ # If set to true, a valid email address is required
+ validate-email: [validateEmail]
+ # Setting this to false will impose a limit of one account per IP address
+ allow-multiple: [allowMultiple]
+ # Used with web registrations that require account activation
+ activation: [activation]
+
+login:
+ strikes:
+ # Amount of times a player can enter an incorrect password before action is taken
+ # Set as 0 to disable
+ amount: [maxStrikes]
+ # What action to take when the strike threshold is reached
+ # Possible values: kick, banip
+ action: [strikeAction]
+ # Length, in seconds, of a ban given by the strike system
+ # Set as 0 for a permanent ban
+ length: [banLength]
+
+password:
+ # Minimum length a password may be
+ min-length: [pwMinLength]
+ # Enable/disable password changes
+ allow-change: [pwAllowChange]
+ # Require at least one of the character types below that are set to true
+ complexity:
+ lowercase: [pwCompLower]
+ uppercase: [pwCompUpper]
+ number: [pwCompNumber]
+ symbol: [pwCompSymbol]
+
+guest:
+ # Amount of time, in seconds, that a player has to log in before they are kicked
+ # Set as 0 to disable
+ timeout: [guestTimeout]
+ # Amount of time, in seconds, between "You must be logged in.." messages
+ notify-cooldown: [notifyCooldown]
+
+session:
+ # Amount of time, in seconds, that a session will remain valid
+ length: [sessionLength]
+ # Verify a player's IP address when resuming a session
+ verifyip: [verifyIp]
+ # Length of time, in seconds, that a player will have godmode upon logging in
+ # set as 0 to disable
+ godmode-length: [godmodeLength]
+
+filter:
+ # Minimum length a players name can be
+ min-length: [filterMinLength]
+ # Characters that may be present in a players name. Use an asterisk (*) to allow all
+ allowed: '[filterAllowed]'
+ # If set to false, players with blank names can connect
+ blankname: [filterBlank]
+
+# INTERNAL USE ONLY! DO NOT TOUCH!
+version: [version]
\ No newline at end of file
diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml
new file mode 100644
index 0000000..0d3e4e4
--- /dev/null
+++ b/src/main/resources/messages.yml
@@ -0,0 +1,87 @@
+join:
+ register: '[joinRegister]'
+ login: '[joinLogin]'
+ error:
+ banned: '[joinErrBanned]'
+ online: '[joinErrOnline]'
+ name: '[joinErrName]'
+
+register:
+ usage: '[regUsage]'
+ success: '[regSuccess]'
+ error:
+ disabled: '[regErrDisabled]'
+ registered: '[regErrRegistered]'
+ multiple: '[regErrMultiple]'
+ password: '[regErrPassword]'
+ email: '[regErrEmail]'
+
+login:
+ usage: '[loginUsage]'
+ success: '[loginSuccess]'
+ error:
+ registered: '[loginErrRegistered]'
+ logged: '[loginErrLogged]'
+ password: '[loginErrPassword]'
+ activate: '[loginErrActivate]'
+
+logout:
+ success: '[logoutSuccess]'
+ error:
+ logged: '[logoutErrLogged]'
+
+changepw:
+ usage: '[cpwUsage]'
+ success: '[cpwSuccess]'
+ error:
+ disabled: '[cpwErrDisabled]'
+ logged: '[cpwErrLogged]'
+ incorrect: '[cpwErrIncorrect]'
+ invalid: '[cpwErrInvalid]'
+
+admin:
+ unknown: '[admnUnknown]'
+ permission: '[admnPermission]'
+ register:
+ usage: '[admnRegUsage]'
+ registered: '[admnRegRegistered]'
+ success: '[admnRegSuccess]'
+ changepw:
+ usage: '[admnCpwUsage]'
+ registered: '[admnCpwRegistered]'
+ success: '[admnCpwSuccess]'
+ logout:
+ usage: '[admnLogoutUsage]'
+ logged: '[admnLogoutLogged]'
+ success: '[admnLogoutSuccess]'
+ unregister:
+ usage: '[admnUnregUsage]'
+ registered: '[admnUnregRegistered]'
+ success:
+ target: '[admnUnregSuccessTgt]'
+ player: '[admnUnregSuccessPlyr]'
+ location:
+ usage: '[admnLocUsage]'
+ set:
+ success: '[admnLocSetSuccess]'
+ remove:
+ no: '[admnLocRmvNo]'
+ success: '[admnLocRmvSuccess]'
+ config:
+ usage: '[admnConfUsage]'
+ no: '[admnConfNo]'
+ desc: '[admnConfDesc]'
+ invalid: '[admnConfInvalid]'
+ success: '[admnConfSuccess]'
+ reload:
+ sucess: '[admnReloadSuccess]'
+
+misc:
+ illegal: '[miscIllegal]'
+ reloaded: '[miscReloaded]'
+ kick:
+ timeout: '[miscKickTimeout]'
+ strike: '[miscKickStrike]'
+
+# INTERNAL USE ONLY! DO NOT TOUCH!
+version: [version]
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..a9f3a1d
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,32 @@
+name: xAuth
+main: com.cypherx.xauth.xAuth
+version: 2.0 [Dev]
+description: Offline-Mode Security Suite
+author: CypherX
+database: false
+commands:
+ register:
+ description: Create an account linked to your player name
+ usage: / [email]
+ login:
+ aliases: [l]
+ description: Authenticate yourself as the account owner
+ usage: /
+ changepw:
+ aliases: [changepassword, changepass, cpw]
+ description: Change your password
+ usage: /
+ logout:
+ description: Terminate your session early
+ usage: /
+ xauth:
+ aliases: [x]
+ description: All of the xAuth Admin commands
+ usage: |
+ / register [email]
+ / changepw
+ / logout
+ / unregister
+ / location set|remove
+ / config
+ / reload
\ No newline at end of file