From 3c25f064e224930c7f4729aebbc53d3fa0d11ce5 Mon Sep 17 00:00:00 2001 From: Zach Iverson Date: Sat, 18 Jun 2011 03:55:26 -0400 Subject: [PATCH] sup --- .gitignore | 1 + pom.xml | 100 +++ src/main/java/com/cypherx/xauth/Account.java | 108 ++++ src/main/java/com/cypherx/xauth/Session.java | 50 ++ .../java/com/cypherx/xauth/StrikeBan.java | 31 + .../java/com/cypherx/xauth/TeleLocation.java | 88 +++ src/main/java/com/cypherx/xauth/Util.java | 202 ++++++ .../java/com/cypherx/xauth/Whirlpool.java | 410 +++++++++++++ .../xauth/commands/ChangePasswordCommand.java | 58 ++ .../cypherx/xauth/commands/LoginCommand.java | 62 ++ .../cypherx/xauth/commands/LogoutCommand.java | 35 ++ .../xauth/commands/RegisterCommand.java | 62 ++ .../cypherx/xauth/commands/xAuthCommand.java | 445 ++++++++++++++ .../xauth/datamanager/DataManager.java | 577 ++++++++++++++++++ .../xauth/listeners/xAuthBlockListener.java | 58 ++ .../xauth/listeners/xAuthEntityListener.java | 79 +++ .../xauth/listeners/xAuthPlayerListener.java | 233 +++++++ src/main/java/com/cypherx/xauth/xAuth.java | 315 ++++++++++ .../java/com/cypherx/xauth/xAuthHelp.java | 28 + src/main/java/com/cypherx/xauth/xAuthLog.java | 32 + .../java/com/cypherx/xauth/xAuthMessages.java | 274 +++++++++ .../com/cypherx/xauth/xAuthPermissions.java | 30 + .../java/com/cypherx/xauth/xAuthPlayer.java | 169 +++++ .../java/com/cypherx/xauth/xAuthSettings.java | 193 ++++++ src/main/resources/MANIFEST.MF | 2 + src/main/resources/config.yml | 96 +++ src/main/resources/messages.yml | 87 +++ src/main/resources/plugin.yml | 32 + 28 files changed, 3857 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/com/cypherx/xauth/Account.java create mode 100644 src/main/java/com/cypherx/xauth/Session.java create mode 100644 src/main/java/com/cypherx/xauth/StrikeBan.java create mode 100644 src/main/java/com/cypherx/xauth/TeleLocation.java create mode 100644 src/main/java/com/cypherx/xauth/Util.java create mode 100644 src/main/java/com/cypherx/xauth/Whirlpool.java create mode 100644 src/main/java/com/cypherx/xauth/commands/ChangePasswordCommand.java create mode 100644 src/main/java/com/cypherx/xauth/commands/LoginCommand.java create mode 100644 src/main/java/com/cypherx/xauth/commands/LogoutCommand.java create mode 100644 src/main/java/com/cypherx/xauth/commands/RegisterCommand.java create mode 100644 src/main/java/com/cypherx/xauth/commands/xAuthCommand.java create mode 100644 src/main/java/com/cypherx/xauth/datamanager/DataManager.java create mode 100644 src/main/java/com/cypherx/xauth/listeners/xAuthBlockListener.java create mode 100644 src/main/java/com/cypherx/xauth/listeners/xAuthEntityListener.java create mode 100644 src/main/java/com/cypherx/xauth/listeners/xAuthPlayerListener.java create mode 100644 src/main/java/com/cypherx/xauth/xAuth.java create mode 100644 src/main/java/com/cypherx/xauth/xAuthHelp.java create mode 100644 src/main/java/com/cypherx/xauth/xAuthLog.java create mode 100644 src/main/java/com/cypherx/xauth/xAuthMessages.java create mode 100644 src/main/java/com/cypherx/xauth/xAuthPermissions.java create mode 100644 src/main/java/com/cypherx/xauth/xAuthPlayer.java create mode 100644 src/main/java/com/cypherx/xauth/xAuthSettings.java create mode 100644 src/main/resources/MANIFEST.MF create mode 100644 src/main/resources/config.yml create mode 100644 src/main/resources/messages.yml create mode 100644 src/main/resources/plugin.yml 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 + 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