diff --git a/pom.xml b/pom.xml
index 869cbe815..7e8cd70ba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,786 +1,781 @@
-
- 4.0.0
+
+ 4.0.0
- fr.xephi
- authme
- 5.2-SNAPSHOT
- jar
+ fr.xephi
+ authme
+ 5.2-SNAPSHOT
+ jar
- AuthMeReloaded
- Authentication plugin for CraftBukkit/Spigot!
- 2013
- http://dev.bukkit.org/bukkit-plugins/authme-reloaded/
-
+ AuthMeReloaded
+ Authentication plugin for CraftBukkit/Spigot!
+ 2013
+ http://dev.bukkit.org/bukkit-plugins/authme-reloaded/
+
-
- AuthMe-Team
- https://github.com/AuthMe-Team
-
+
+ AuthMe-Team
+ https://github.com/AuthMe-Team
+
-
- scm:git:https://github.com/Xephi/AuthMeReloaded.git
- scm:git:git@github.com:Xephi/AuthMeReloaded.git
- http://github.com/Xephi/AuthMeReloaded
-
+
+ scm:git:https://github.com/Xephi/AuthMeReloaded.git
+ scm:git:git@github.com:Xephi/AuthMeReloaded.git
+ http://github.com/Xephi/AuthMeReloaded
+
-
- jenkins
- http://ci.xephi.fr/job/AuthMeReloaded/
-
+
+ jenkins
+ http://ci.xephi.fr/job/AuthMeReloaded/
+
-
- GitHub
- https://github.com/Xephi/AuthMeReloaded/issues
-
+
+ GitHub
+ https://github.com/Xephi/AuthMeReloaded/issues
+
-
-
- The GNU General Public Licence version 3 (GPLv3)
- http://www.gnu.org/licenses/gpl-3.0.html
-
-
+
+
+ The GNU General Public Licence version 3 (GPLv3)
+ http://www.gnu.org/licenses/gpl-3.0.html
+
+
-
- 3.3.3
-
+
+ 3.3.3
+
-
- UTF-8
+
+ UTF-8
-
- AuthMe
- fr.xephi.authme.AuthMe
- Xephi, sgdc3, DNx5, timvisee, games647, ljacqu
- Unknown
+
+ AuthMe
+ fr.xephi.authme.AuthMe
+ Xephi, sgdc3, DNx5, timvisee, games647, ljacqu
+ Unknown
-
- 1.7
+
+ 1.7
-
- 1.8.8-R0.1-SNAPSHOT
-
+
+ 1.8.8-R0.1-SNAPSHOT
+
-
-
- jenkins
-
-
- env.BUILD_NUMBER
-
-
-
- ${env.BUILD_NUMBER}
-
-
-
+
+
+ jenkins
+
+
+ env.BUILD_NUMBER
+
+
+
+ ${env.BUILD_NUMBER}
+
+
+
-
- AuthMe-${project.version}
- src/main/java
- src/test/java
+
+ AuthMe-${project.version}
+ src/main/java
+ src/test/java
-
-
- .
- true
- src/main/resources/
-
- plugin.yml
-
-
-
- .
- true
- src/main/resources/
-
- email.html
-
-
-
- .
- false
- src/main/resources/
-
- *.yml
-
-
- plugin.yml
-
-
-
- ./messages/
- false
- src/main/resources/messages/
-
- *.yml
-
-
-
-
-
- src/test/resources
-
-
+
+
+ .
+ true
+ src/main/resources/
+
+ plugin.yml
+
+
+
+ .
+ true
+ src/main/resources/
+
+ email.html
+
+
+
+ .
+ false
+ src/main/resources/
+
+ *.yml
+
+
+ plugin.yml
+
+
+
+ ./messages/
+ false
+ src/main/resources/messages/
+
+ *.yml
+
+
+
+
+
+ src/test/resources
+
+
-
-
-
-
- org.eclipse.m2e
- lifecycle-mapping
- 1.0.0
-
-
-
-
-
- org.codehaus.mojo
- buildnumber-maven-plugin
- [1.0,)
-
- create-timestamp
-
-
-
-
- true
- true
-
-
-
-
-
-
-
-
-
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+ org.codehaus.mojo
+ buildnumber-maven-plugin
+ [1.0,)
+
+ create-timestamp
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.3
-
-
- ${javaVersion}
-
-
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.3
+
+
+ ${javaVersion}
+
+
-
- org.codehaus.mojo
- buildnumber-maven-plugin
- 1.4
-
- dd-MM-yy_HH-mm
- build.time
-
-
-
- generate-resources
-
- create-timestamp
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.4.2
-
- false
- false
-
-
- org.mcstats
- fr.xephi.authme
-
-
- com.google.gson
- fr.xephi.authme.libs.gson
-
-
- com.zaxxer.hikari
- fr.xephi.authme.libs.hikari
-
-
- org.slf4j
- fr.xephi.authme.libs.slf4j
-
-
- com.maxmind.geoip
- fr.xephi.authme.libs.geoip
-
-
- net.ricecode.similarity
- fr.xephi.authme.libs.similarity
-
-
-
-
-
- package
-
- shade
-
-
-
-
-
-
- org.jacoco
- jacoco-maven-plugin
- 0.7.5.201505241946
-
-
- prepare-agent
-
- prepare-agent
-
-
-
-
-
-
- org.eluder.coveralls
- coveralls-maven-plugin
- 4.1.0
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 2.10.3
-
- fr.xephi.authme.api.*:fr.xephi.authme.events.*
-
-
+
+ org.codehaus.mojo
+ buildnumber-maven-plugin
+ 1.4
+
+ dd-MM-yy_HH-mm
+ build.time
+
+
- attach-javadocs
+ generate-resources
- jar
+ create-timestamp
-
-
-
+
-
-
-
- spigot-repo
- http://hub.spigotmc.org/nexus/content/groups/public
-
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.4.2
+
+ false
+ false
+
+
+ org.mcstats
+ fr.xephi.authme
+
+
+ com.google.gson
+ fr.xephi.authme.libs.gson
+
+
+ com.zaxxer.hikari
+ fr.xephi.authme.libs.hikari
+
+
+ org.slf4j
+ fr.xephi.authme.libs.slf4j
+
+
+ com.maxmind.geoip
+ fr.xephi.authme.libs.geoip
+
+
+ net.ricecode.similarity
+ fr.xephi.authme.libs.similarity
+
+
+
+
+
+ package
+
+ shade
+
+
+
+
-
-
- ess-repo
- http://ci.drtshock.net/plugin/repository/everything
-
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.7.5.201505241946
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+
+
-
-
- minelink-thirdparty
- http://repo.minelink.net/content/repositories/public
-
+
+ org.eluder.coveralls
+ coveralls-maven-plugin
+ 4.1.0
+
+
-
-
- dmulloy2-repo
- http://repo.dmulloy2.net/content/groups/public/
-
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.10.3
+
+ UTF-8
+ UTF-8
+ true
+
+
+
+
-
-
- onarandombox
- http://repo.onarandombox.com/content/groups/public
-
+
+
+
+ spigot-repo
+ http://hub.spigotmc.org/nexus/content/groups/public
+
-
-
- vault-repo
- http://nexus.theyeticave.net/content/repositories/pub_releases
-
+
+
+ ess-repo
+ http://ci.drtshock.net/plugin/repository/everything
+
-
-
- luricos-releases
- http://repo.luricos.de/content/repositories/releases
-
+
+
+ minelink-thirdparty
+ http://repo.minelink.net/content/repositories/public
+
-
-
- xephi-repo
- http://ci.xephi.fr/plugin/repository/everything/
-
+
+
+ dmulloy2-repo
+ http://repo.dmulloy2.net/content/groups/public/
+
-
-
- pex-repo
- http://pex-repo.aoeu.xyz/
-
-
+
+
+ onarandombox
+ http://repo.onarandombox.com/content/groups/public
+
-
-
-
- com.zaxxer
- HikariCP
- 2.4.3
- compile
-
-
- slf4j-api
- org.slf4j
-
-
- true
-
-
- org.slf4j
- slf4j-jdk14
- 1.7.13
- compile
- true
-
+
+
+ vault-repo
+ http://nexus.theyeticave.net/content/repositories/pub_releases
+
-
-
- org.apache.logging.log4j
- log4j-core
-
- 2.0-beta9
- provided
- true
-
+
+
+ luricos-releases
+ http://repo.luricos.de/content/repositories/releases
+
-
-
- org.apache.commons
- commons-email
- 1.4
- compile
- true
-
+
+
+ xephi-repo
+ http://ci.xephi.fr/plugin/repository/everything/
+
-
-
- com.google.code.gson
- gson
- 2.5
- compile
- true
-
+
+
+ pex-repo
+ http://pex-repo.aoeu.xyz/
+
+
-
-
- com.maxmind.geoip
- geoip-api
- 1.2.15
- compile
- true
-
+
+
+
+ com.zaxxer
+ HikariCP
+ 2.4.3
+ compile
+
+
+ slf4j-api
+ org.slf4j
+
+
+ true
+
+
+ org.slf4j
+ slf4j-jdk14
+ 1.7.13
+ compile
+ true
+
-
-
- org.mcstats.bukkit
- metrics
- R8-SNAPSHOT
- compile
-
-
- org.bukkit
- bukkit
-
-
- true
-
+
+
+ org.apache.logging.log4j
+ log4j-core
+
+ 2.0-beta9
+ provided
+ true
+
-
-
- org.bukkit
- bukkit
- ${bukkitVersion}
- provided
- true
-
-
- junit
- junit
-
-
- json-simple
- com.googlecode.json-simple
-
-
- gson
- com.google.code.gson
-
-
- persistence-api
- javax.persistence
-
-
-
+
+
+ org.apache.commons
+ commons-email
+ 1.4
+ compile
+ true
+
-
-
- com.comphenix.protocol
- ProtocolLib
- 3.6.5-SNAPSHOT
- provided
- true
-
-
- cglib-nodep
- cglib
-
-
- BukkitExecutors
- com.comphenix.executors
-
-
-
+
+
+ com.google.code.gson
+ gson
+ 2.5
+ compile
+ true
+
-
-
- ru.tehkode
- PermissionsEx
- 1.23.1
- provided
-
-
- org.bukkit
- bukkit
-
-
- net.gravitydevelopment.updater
- updater
-
-
- commons-dbcp
- commons-dbcp
-
-
- AccountsClient
- com.mojang
-
-
-
+
+
+ com.maxmind.geoip
+ geoip-api
+ 1.2.15
+ compile
+ true
+
-
-
- org.anjocaido
- groupmanagerx
- 2.2-SNAPSHOT
- provided
-
-
- org.bukkit
- bukkit
-
-
-
+
+
+ org.mcstats.bukkit
+ metrics
+ R8-SNAPSHOT
+ compile
+
+
+ org.bukkit
+ bukkit
+
+
+ true
+
-
-
- de.bananaco
- bPermissions
- 2.12-DEV
- provided
-
-
- org.bukkit
- bukkit
-
-
-
+
+
+ org.bukkit
+ bukkit
+ ${bukkitVersion}
+ provided
+ true
+
+
+ junit
+ junit
+
+
+ json-simple
+ com.googlecode.json-simple
+
+
+ gson
+ com.google.code.gson
+
+
+ persistence-api
+ javax.persistence
+
+
+
-
-
- org.tyrannyofheaven.bukkit
- zPermissions
- 1.3-SNAPSHOT
- provided
-
-
- org.bukkit
- bukkit
-
-
- com.sk89q
- worldguard
-
-
- com.sk89q
- worldedit
-
-
- VaultAPI
- net.milkbowl.vault
-
-
- uuidprovider
- net.kaikk.mc
-
-
- ToHPluginUtils
- org.tyrannyofheaven.bukkit
-
-
-
+
+
+ com.comphenix.protocol
+ ProtocolLib
+ 3.6.5-SNAPSHOT
+ provided
+ true
+
+
+ cglib-nodep
+ cglib
+
+
+ BukkitExecutors
+ com.comphenix.executors
+
+
+
-
-
- net.milkbowl.vault
- VaultAPI
- 1.5
- provided
-
-
- org.bukkit
- bukkit
-
-
- org.bukkit
- craftbukkit
-
-
- true
-
+
+
+ ru.tehkode
+ PermissionsEx
+ 1.23.1
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+ net.gravitydevelopment.updater
+ updater
+
+
+ commons-dbcp
+ commons-dbcp
+
+
+ AccountsClient
+ com.mojang
+
+
+
-
-
- com.onarandombox.multiversecore
- Multiverse-Core
- 2.5
- jar
- provided
-
-
- org.bukkit
- bukkit
-
-
- org.bukkit
- craftbukkit
-
-
- AllPay
- com.fernferret.allpay
-
-
- Vault
- net.milkbowl.vault
-
-
- VaultAPI
- net.milkbowl.vault
-
-
- CommandHandler
- com.pneumaticraft.commandhandler
-
-
- SerializationConfig
- me.main__.util
-
-
- Logging
- com.dumptruckman.minecraft
-
-
- metrics
- org.mcstats.bukkit
-
-
- buscript
- com.dumptruckman.minecraft
-
-
- junit
- junit
-
-
- true
-
+
+
+ org.anjocaido
+ groupmanagerx
+ 2.2-SNAPSHOT
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+
-
-
- net.ess3
- EssentialsX
- 2.0.1-SNAPSHOT
- provided
-
-
- org.spigotmc
- spigot-api
-
-
- true
-
+
+
+ de.bananaco
+ bPermissions
+ 2.12-DEV
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+
-
-
- net.minelink
- CombatTagPlus
- 1.2.1-SNAPSHOT
- provided
-
-
- org.bukkit
- bukkit
-
-
- org.bukkit
- craftbukkit
-
-
- CombatTagPlusHook
- net.minelink
-
-
- CombatTagPlusFactions-v1_6
- net.minelink
-
-
- CombatTagPlusCompat-v1_7_R3
- net.minelink
-
-
- CombatTagPlusFactions-v1_8
- net.minelink
-
-
- CombatTagPlusCompat-v1_7_R4
- net.minelink
-
-
- CombatTagPlusWG-v5
- net.minelink
-
-
- CombatTagPlusWG-v6
- net.minelink
-
-
- CombatTagPlusCompat-API
- net.minelink
-
-
- CombatTagPlusFactions-v2_6
- net.minelink
-
-
- CombatTagPlusCompat-v1_8_R3
- net.minelink
-
-
- CombatTagPlusFactions-v2_7
- net.minelink
-
-
- CombatTagPlusCompat-v1_8_R2
- net.minelink
-
-
- CombatTagPlusCompat-v1_8_R1
- net.minelink
-
-
- metrics-lite
- org.mcstats.bukkit
-
-
- true
-
+
+
+ org.tyrannyofheaven.bukkit
+ zPermissions
+ 1.3-SNAPSHOT
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+ com.sk89q
+ worldguard
+
+
+ com.sk89q
+ worldedit
+
+
+ VaultAPI
+ net.milkbowl.vault
+
+
+ uuidprovider
+ net.kaikk.mc
+
+
+ ToHPluginUtils
+ org.tyrannyofheaven.bukkit
+
+
+
-
-
- de.luricos.bukkit
- xAuth
- 2.6
- provided
-
-
- org.bukkit
- bukkit
-
-
- org.bukkit
- craftbukkit
-
-
- updater
- net.gravitydevelopment.updater
-
-
- lombok
- org.projectlombok
-
-
- EssentialsGroupManager
- net.ess3
-
-
- PermissionsEx
- ru.tehkode
-
-
- AccountsClient
- com.mojang
-
-
- log4j-core
- org.apache.logging.log4j
-
-
- true
-
+
+
+ net.milkbowl.vault
+ VaultAPI
+ 1.5
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+ org.bukkit
+ craftbukkit
+
+
+ true
+
-
-
- junit
- junit
- test
- 4.12
- true
-
-
- org.hamcrest
- java-hamcrest
- test
- 2.0.0.0
- true
-
-
- org.mockito
- mockito-core
- test
- 2.0.5-beta
- true
-
-
- hamcrest-core
- org.hamcrest
-
-
-
+
+
+ com.onarandombox.multiversecore
+ Multiverse-Core
+ 2.5
+ jar
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+ org.bukkit
+ craftbukkit
+
+
+ AllPay
+ com.fernferret.allpay
+
+
+ Vault
+ net.milkbowl.vault
+
+
+ VaultAPI
+ net.milkbowl.vault
+
+
+ CommandHandler
+ com.pneumaticraft.commandhandler
+
+
+ SerializationConfig
+ me.main__.util
+
+
+ Logging
+ com.dumptruckman.minecraft
+
+
+ metrics
+ org.mcstats.bukkit
+
+
+ buscript
+ com.dumptruckman.minecraft
+
+
+ junit
+ junit
+
+
+ true
+
-
-
- net.ricecode
- string-similarity
- 1.0.0
- compile
- true
-
-
+
+
+ net.ess3
+ EssentialsX
+ 2.0.1-SNAPSHOT
+ provided
+
+
+ org.spigotmc
+ spigot-api
+
+
+ true
+
+
+
+
+ net.minelink
+ CombatTagPlus
+ 1.2.1-SNAPSHOT
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+ org.bukkit
+ craftbukkit
+
+
+ CombatTagPlusHook
+ net.minelink
+
+
+ CombatTagPlusFactions-v1_6
+ net.minelink
+
+
+ CombatTagPlusCompat-v1_7_R3
+ net.minelink
+
+
+ CombatTagPlusFactions-v1_8
+ net.minelink
+
+
+ CombatTagPlusCompat-v1_7_R4
+ net.minelink
+
+
+ CombatTagPlusWG-v5
+ net.minelink
+
+
+ CombatTagPlusWG-v6
+ net.minelink
+
+
+ CombatTagPlusCompat-API
+ net.minelink
+
+
+ CombatTagPlusFactions-v2_6
+ net.minelink
+
+
+ CombatTagPlusCompat-v1_8_R3
+ net.minelink
+
+
+ CombatTagPlusFactions-v2_7
+ net.minelink
+
+
+ CombatTagPlusCompat-v1_8_R2
+ net.minelink
+
+
+ CombatTagPlusCompat-v1_8_R1
+ net.minelink
+
+
+ metrics-lite
+ org.mcstats.bukkit
+
+
+ true
+
+
+
+
+ de.luricos.bukkit
+ xAuth
+ 2.6
+ provided
+
+
+ org.bukkit
+ bukkit
+
+
+ org.bukkit
+ craftbukkit
+
+
+ updater
+ net.gravitydevelopment.updater
+
+
+ lombok
+ org.projectlombok
+
+
+ EssentialsGroupManager
+ net.ess3
+
+
+ PermissionsEx
+ ru.tehkode
+
+
+ AccountsClient
+ com.mojang
+
+
+ log4j-core
+ org.apache.logging.log4j
+
+
+ true
+
+
+
+
+ junit
+ junit
+ test
+ 4.12
+ true
+
+
+ org.hamcrest
+ java-hamcrest
+ test
+ 2.0.0.0
+ true
+
+
+ org.mockito
+ mockito-core
+ test
+ 2.0.5-beta
+ true
+
+
+ hamcrest-core
+ org.hamcrest
+
+
+
+
+
+
+ net.ricecode
+ string-similarity
+ 1.0.0
+ compile
+ true
+
+
diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java
index 41ba8ff48..70c8bfd6b 100644
--- a/src/main/java/fr/xephi/authme/AuthMe.java
+++ b/src/main/java/fr/xephi/authme/AuthMe.java
@@ -1,6 +1,8 @@
package fr.xephi.authme;
import com.earth2me.essentials.Essentials;
+import com.google.common.base.Charsets;
+import com.google.common.io.Resources;
import com.onarandombox.MultiverseCore.MultiverseCore;
import fr.xephi.authme.api.API;
import fr.xephi.authme.api.NewAPI;
@@ -30,7 +32,6 @@ import fr.xephi.authme.listener.AuthMePlayerListener;
import fr.xephi.authme.listener.AuthMePlayerListener16;
import fr.xephi.authme.listener.AuthMePlayerListener18;
import fr.xephi.authme.listener.AuthMeServerListener;
-import fr.xephi.authme.listener.AuthMeServerStop;
import fr.xephi.authme.listener.AuthMeTabCompletePacketAdapter;
import fr.xephi.authme.mail.SendMailSSL;
import fr.xephi.authme.modules.ModuleManager;
@@ -66,11 +67,8 @@ import org.bukkit.scheduler.BukkitTask;
import org.mcstats.Metrics;
import org.mcstats.Metrics.Graph;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.net.URL;
-import java.net.URLConnection;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
@@ -133,6 +131,7 @@ public class AuthMe extends JavaPlugin {
/**
* Get the plugin's instance.
+ *
* @return AuthMe
*/
public static AuthMe getInstance() {
@@ -141,6 +140,7 @@ public class AuthMe extends JavaPlugin {
/**
* Get the plugin's name.
+ *
* @return The plugin's name.
*/
public static String getPluginName() {
@@ -149,6 +149,7 @@ public class AuthMe extends JavaPlugin {
/**
* Get the plugin's version.
+ *
* @return The plugin's version.
*/
public static String getPluginVersion() {
@@ -157,6 +158,7 @@ public class AuthMe extends JavaPlugin {
/**
* Get the plugin's build number.
+ *
* @return The plugin's build number.
*/
public static String getPluginBuildNumber() {
@@ -165,6 +167,7 @@ public class AuthMe extends JavaPlugin {
/**
* Get the plugin's Settings.
+ *
* @return Plugin's settings.
*/
public Settings getSettings() {
@@ -173,6 +176,7 @@ public class AuthMe extends JavaPlugin {
/**
* Get the Messages instance.
+ *
* @return Plugin's messages.
*/
public Messages getMessages() {
@@ -272,7 +276,6 @@ public class AuthMe extends JavaPlugin {
new PerformBackup(plugin).doBackup(PerformBackup.BackupCause.START);
-
// Setup the inventory backup
playerBackup = new JsonCache();
@@ -303,13 +306,6 @@ public class AuthMe extends JavaPlugin {
// Show settings warnings
showSettingsWarnings();
- // Register a server shutdown hook
- try {
- Runtime.getRuntime().addShutdownHook(new AuthMeServerStop(this));
- } catch (Exception e){
- e.printStackTrace();
- }
-
// Sponsor messages
ConsoleLogger.info("AuthMe hooks perfectly with the VeryGames server hosting!");
ConsoleLogger.info("Development builds are available on our jenkins, thanks to f14stelt.");
@@ -435,7 +431,7 @@ public class AuthMe extends JavaPlugin {
// Set up the API
api = new NewAPI(this);
- // Setup the old deprecated API
+ // Set up the deprecated API
new API(this);
}
@@ -517,10 +513,10 @@ public class AuthMe extends JavaPlugin {
public void onDisable() {
// Save player data
Collection extends Player> players = Utils.getOnlinePlayers();
- if (players != null) {
- for (Player player : players) {
- this.savePlayer(player);
- }
+ for (Player player : players) {
+ savePlayer(player);
+ // TODO: add a MessageKey
+ player.kickPlayer("Server is restarting or AuthMe plugin was disabled.");
}
// Do backup on stop if enabled
@@ -593,16 +589,16 @@ public class AuthMe extends JavaPlugin {
// TODO: Move this to another place maybe ?
if (Settings.getPasswordHash == HashAlgorithm.PLAINTEXT) {
- ConsoleLogger.showError("Your HashAlgorithm has been detected as plaintext and is now deprecated; " +
+ ConsoleLogger.showError("Your HashAlgorithm has been detected as plaintext and is now deprecated; " +
"it will be changed and hashed now to the AuthMe default hashing method");
- for (PlayerAuth auth : database.getAllAuths()) {
+ for (PlayerAuth auth : database.getAllAuths()) {
HashedPassword hashedPassword = passwordSecurity.computeHash(
HashAlgorithm.SHA256, auth.getPassword().getHash(), auth.getNickname());
auth.setPassword(hashedPassword);
- database.updatePassword(auth);
- }
- Settings.setValue("settings.security.passwordHash", "SHA256");
- Settings.reload();
+ database.updatePassword(auth);
+ }
+ Settings.setValue("settings.security.passwordHash", "SHA256");
+ Settings.reload();
}
if (Settings.isCachingEnabled) {
@@ -715,10 +711,9 @@ public class AuthMe extends JavaPlugin {
inventoryProtector = null;
}
}
- if (tabComplete == null)
- {
- tabComplete = new AuthMeTabCompletePacketAdapter(this);
- tabComplete.register();
+ if (tabComplete == null) {
+ tabComplete = new AuthMeTabCompletePacketAdapter(this);
+ tabComplete.register();
}
}
@@ -889,50 +884,34 @@ public class AuthMe extends JavaPlugin {
* Gets a player's real IP through VeryGames method.
*
* @param player The player to process.
- *
*/
@Deprecated
public void getVerygamesIp(final Player player) {
- final String name = player.getName().toLowerCase();
- Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
- @Override
- public void run() {
- String realIP = player.getAddress().getAddress().getHostAddress();
- if (realIp.containsKey(name))
- realIP = realIp.get(name);
- String sUrl = "http://monitor-1.verygames.net/api/?action=ipclean-real-ip&out=raw&ip=%IP%&port=%PORT%";
- sUrl = sUrl.replace("%IP%", realIP)
- .replace("%PORT%", "" + player.getAddress().getPort());
- try {
- URL url = new URL(sUrl);
- URLConnection urlCon = url.openConnection();
- urlCon.setConnectTimeout(5000);
- urlCon.setReadTimeout(5000);
- try (BufferedReader in = new BufferedReader(new InputStreamReader(urlCon.getInputStream()))) {
- String inputLine = in.readLine();
- if (!StringUtils.isEmpty(inputLine) && !inputLine.equalsIgnoreCase("error")
- && !inputLine.contains("error")) {
- realIP = inputLine;
- }
- } catch (IOException e) {
- ConsoleLogger.showError("Could not read from Very Games API - " + StringUtils.formatException(e));
- }
- } catch (IOException e) {
- ConsoleLogger.showError("Could not fetch Very Games API with URL '" + sUrl + "' - "
- + StringUtils.formatException(e));
- }
- if (realIp.containsKey(name))
- realIp.remove(name);
- realIp.putIfAbsent(name, realIP);
- }
- });
+ final String name = player.getName().toLowerCase();
+ String currentIp = player.getAddress().getAddress().getHostAddress();
+ if (realIp.containsKey(name)) {
+ currentIp = realIp.get(name);
+ }
+ String sUrl = "http://monitor-1.verygames.net/api/?action=ipclean-real-ip&out=raw&ip=%IP%&port=%PORT%";
+ sUrl = sUrl.replace("%IP%", currentIp).replace("%PORT%", "" + player.getAddress().getPort());
+ try {
+ String result = Resources.toString(new URL(sUrl), Charsets.UTF_8);
+ if (!StringUtils.isEmpty(result) && !result.equalsIgnoreCase("error") && !result.contains("error")) {
+ currentIp = result;
+ realIp.put(name, currentIp);
+ }
+ } catch (IOException e) {
+ ConsoleLogger.showError("Could not fetch Very Games API with URL '" +
+ sUrl + "' - " + StringUtils.formatException(e));
+ }
}
public String getIP(final Player player) {
final String name = player.getName().toLowerCase();
String ip = player.getAddress().getAddress().getHostAddress();
- if (realIp.containsKey(name))
+ if (realIp.containsKey(name)) {
ip = realIp.get(name);
+ }
return ip;
}
@@ -983,6 +962,8 @@ public class AuthMe extends JavaPlugin {
/**
* Return the management instance.
+ *
+ * @return management The Management
*/
public Management getManagement() {
return management;
diff --git a/src/main/java/fr/xephi/authme/DataManager.java b/src/main/java/fr/xephi/authme/DataManager.java
index 451667ad1..e0afe6bfc 100644
--- a/src/main/java/fr/xephi/authme/DataManager.java
+++ b/src/main/java/fr/xephi/authme/DataManager.java
@@ -1,12 +1,5 @@
package fr.xephi.authme;
-import fr.xephi.authme.permission.PermissionsManager;
-import fr.xephi.authme.settings.Settings;
-import fr.xephi.authme.util.Utils;
-import org.bukkit.Bukkit;
-import org.bukkit.OfflinePlayer;
-import org.bukkit.entity.Player;
-
import java.io.File;
import java.util.List;
import java.util.concurrent.Callable;
@@ -14,6 +7,14 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import org.bukkit.Bukkit;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.entity.Player;
+
+import fr.xephi.authme.permission.PermissionsManager;
+import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.util.Utils;
+
/**
*/
public class DataManager {
@@ -65,7 +66,7 @@ public class DataManager {
/**
* Method purgeAntiXray.
*
- * @param cleared List
+ * @param cleared List of String
*/
public synchronized void purgeAntiXray(List cleared) {
int i = 0;
@@ -90,7 +91,7 @@ public class DataManager {
/**
* Method purgeLimitedCreative.
*
- * @param cleared List
+ * @param cleared List of String
*/
public synchronized void purgeLimitedCreative(List cleared) {
int i = 0;
@@ -127,7 +128,7 @@ public class DataManager {
/**
* Method purgeDat.
*
- * @param cleared List
+ * @param cleared List of String
*/
public synchronized void purgeDat(List cleared) {
int i = 0;
@@ -160,7 +161,7 @@ public class DataManager {
/**
* Method purgeEssentials.
*
- * @param cleared List
+ * @param cleared List of String
*/
@SuppressWarnings("deprecation")
public void purgeEssentials(List cleared) {
diff --git a/src/main/java/fr/xephi/authme/api/NewAPI.java b/src/main/java/fr/xephi/authme/api/NewAPI.java
index 6f42432e1..03fed1a80 100644
--- a/src/main/java/fr/xephi/authme/api/NewAPI.java
+++ b/src/main/java/fr/xephi/authme/api/NewAPI.java
@@ -1,15 +1,16 @@
package fr.xephi.authme.api;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Server;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.util.Utils;
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.Server;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.Plugin;
/**
* The current API of AuthMe.
@@ -76,7 +77,7 @@ public class NewAPI {
}
/**
- * @param player
+ * @param player a Player
*
* @return true if player is a npc
*/
@@ -85,7 +86,7 @@ public class NewAPI {
}
/**
- * @param player
+ * @param player a Player
*
* @return true if the player is unrestricted
*/
diff --git a/src/main/java/fr/xephi/authme/cache/auth/PlayerAuth.java b/src/main/java/fr/xephi/authme/cache/auth/PlayerAuth.java
index b8c7552a2..41672c0c9 100644
--- a/src/main/java/fr/xephi/authme/cache/auth/PlayerAuth.java
+++ b/src/main/java/fr/xephi/authme/cache/auth/PlayerAuth.java
@@ -1,11 +1,12 @@
package fr.xephi.authme.cache.auth;
-import fr.xephi.authme.security.crypts.HashedPassword;
-import org.bukkit.Location;
-
import static com.google.common.base.Objects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
+import org.bukkit.Location;
+
+import fr.xephi.authme.security.crypts.HashedPassword;
+
/**
*/
@@ -24,7 +25,7 @@ public class PlayerAuth {
private String realName;
/**
- *
+ * @param serialized String
*/
public PlayerAuth(String serialized) {
this.deserialize(serialized);
@@ -340,6 +341,8 @@ public class PlayerAuth {
/**
* Method to deserialize PlayerAuth
+ *
+ * @param str String
*/
public void deserialize(String str) {
String[] args = str.split(";");
diff --git a/src/main/java/fr/xephi/authme/command/CommandDescription.java b/src/main/java/fr/xephi/authme/command/CommandDescription.java
index d398af674..22a3f05cd 100644
--- a/src/main/java/fr/xephi/authme/command/CommandDescription.java
+++ b/src/main/java/fr/xephi/authme/command/CommandDescription.java
@@ -12,12 +12,13 @@ import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Arrays.asList;
/**
- * Command description - defines which labels ("names") will lead to a command and points to the
+ * Command description – defines which labels ("names") will lead to a command and points to the
* {@link ExecutableCommand} implementation that executes the logic of the command.
*
- * CommandDescription instances are built hierarchically and have one parent or {@code null} for base commands
- * (main commands such as /authme) and may have multiple children extending the mapping of the parent: e.g. if
- * /authme has a child whose label is "register", then "/authme register" is the command that the child defines.
+ * CommandDescription instances are built hierarchically: they have one parent, or {@code null} for base commands
+ * (main commands such as {@code /authme}), and may have multiple children extending the mapping of the parent: e.g. if
+ * {@code /authme} has a child whose label is {@code "register"}, then {@code /authme register} is the command that
+ * the child defines.
*/
public class CommandDescription {
@@ -102,10 +103,11 @@ public class CommandDescription {
}
/**
- * Get all relative labels of this command. For example, if this object describes "/authme register" and
- * "/authme r", then "r" and "register" are the relative labels, whereas "authme" is the label of the parent.
+ * Return all relative labels of this command. For example, if this object describes {@code /authme register} and
+ * {@code /authme r}, then it will return a list with {@code register} and {@code r}. The parent label
+ * {@code authme} is not returned.
*
- * @return All relative labels.
+ * @return All labels of the command description.
*/
public List getLabels() {
return labels;
diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java
index 8a3480eec..e3ab671b4 100644
--- a/src/main/java/fr/xephi/authme/command/CommandHandler.java
+++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java
@@ -1,11 +1,12 @@
package fr.xephi.authme.command;
-import fr.xephi.authme.util.StringUtils;
-import org.bukkit.command.CommandSender;
-
import java.util.ArrayList;
import java.util.List;
+import org.bukkit.command.CommandSender;
+
+import fr.xephi.authme.util.StringUtils;
+
/**
* The AuthMe command handler, responsible for mapping incoming commands to the correct {@link CommandDescription}
* or to display help messages for unknown invocations.
@@ -16,6 +17,8 @@ public class CommandHandler {
/**
* Create a command handler.
+ *
+ * @param commandService The CommandService instance
*/
public CommandHandler(CommandService commandService) {
this.commandService = commandService;
@@ -45,6 +48,12 @@ public class CommandHandler {
return !FoundResultStatus.MISSING_BASE_COMMAND.equals(result.getResultStatus());
}
+ /**
+ * Execute the command for the given command sender.
+ *
+ * @param sender The sender which initiated the command
+ * @param result The mapped result
+ */
private void executeCommand(CommandSender sender, FoundCommandResult result) {
ExecutableCommand executableCommand = result.getCommandDescription().getExecutableCommand();
List arguments = result.getArguments();
diff --git a/src/main/java/fr/xephi/authme/command/CommandService.java b/src/main/java/fr/xephi/authme/command/CommandService.java
index b53fc2e8d..08a2790e8 100644
--- a/src/main/java/fr/xephi/authme/command/CommandService.java
+++ b/src/main/java/fr/xephi/authme/command/CommandService.java
@@ -1,5 +1,9 @@
package fr.xephi.authme.command;
+import java.util.List;
+
+import org.bukkit.command.CommandSender;
+
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.datasource.DataSource;
@@ -8,9 +12,6 @@ import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.security.PasswordSecurity;
-import org.bukkit.command.CommandSender;
-
-import java.util.List;
/**
* Service for implementations of {@link ExecutableCommand} to execute some common tasks.
@@ -31,6 +32,7 @@ public class CommandService {
* @param commandMapper Command mapper
* @param helpProvider Help provider
* @param messages Messages instance
+ * @param passwordSecurity The Password Security instance
*/
public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages,
PasswordSecurity passwordSecurity) {
@@ -51,6 +53,13 @@ public class CommandService {
messages.send(sender, messageKey);
}
+ /**
+ * Send a message to a player.
+ *
+ * @param sender The command sender to send the message to
+ * @param messageKey The message key to send
+ * @param replacements The replacement arguments for the message key's tags
+ */
public void send(CommandSender sender, MessageKey messageKey, String... replacements) {
messages.send(sender, messageKey, replacements);
}
@@ -119,7 +128,7 @@ public class CommandService {
}
/**
- * Returns the management instance of the plugin.
+ * Return the management instance of the plugin.
*
* @return The Management instance linked to the AuthMe instance
*/
@@ -127,11 +136,22 @@ public class CommandService {
return authMe.getManagement();
}
+ /**
+ * Return the permissions manager.
+ *
+ * @return the permissions manager
+ */
public PermissionsManager getPermissionsManager() {
// TODO ljacqu 20151226: Might be nicer to pass the perm manager via constructor
return authMe.getPermissionsManager();
}
+ /**
+ * Retrieve a message by its message key.
+ *
+ * @param key The message to retrieve
+ * @return The message
+ */
public String[] retrieveMessage(MessageKey key) {
return messages.retrieve(key);
}
diff --git a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java
index 53de7f4d2..520eec243 100644
--- a/src/main/java/fr/xephi/authme/command/FoundCommandResult.java
+++ b/src/main/java/fr/xephi/authme/command/FoundCommandResult.java
@@ -5,7 +5,7 @@ import java.util.List;
/**
* Result of a command mapping by {@link CommandHandler}. An object of this class represents a successful mapping
* as well as erroneous ones, as communicated with {@link FoundResultStatus}.
- *
+ *
* Fields other than {@link FoundResultStatus} are available depending, among other factors, on the status:
*
*
{@link FoundResultStatus#SUCCESS} entails that mapping the input to a command was successful. Therefore,
diff --git a/src/main/java/fr/xephi/authme/command/PlayerCommand.java b/src/main/java/fr/xephi/authme/command/PlayerCommand.java
index a607803b7..2d7aca0b9 100644
--- a/src/main/java/fr/xephi/authme/command/PlayerCommand.java
+++ b/src/main/java/fr/xephi/authme/command/PlayerCommand.java
@@ -1,10 +1,10 @@
package fr.xephi.authme.command;
+import java.util.List;
+
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import java.util.List;
-
/**
* Common base type for player-only commands, handling the verification that the command sender is indeed a player.
*/
@@ -35,7 +35,7 @@ public abstract class PlayerCommand implements ExecutableCommand {
/**
* Return an alternative command (textual representation) that is not restricted to players only.
- * Example: "authme register <playerName> <password>"
+ * Example: {@code "authme register "}
*
* @return Alternative command not only for players, or null if not applicable
*/
diff --git a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
index 50c833538..e573c6d04 100644
--- a/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
+++ b/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
@@ -7,6 +7,7 @@ import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalListeners;
import com.google.common.cache.RemovalNotification;
+import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.security.crypts.HashedPassword;
@@ -52,15 +53,6 @@ public class CacheDataSource implements DataSource {
});
}
- /**
- * Method isAuthAvailable.
- *
- * @param user String
- *
- * @return boolean
- *
- * @see fr.xephi.authme.datasource.DataSource#isAuthAvailable(String)
- */
@Override
public synchronized boolean isAuthAvailable(String user) {
return getAuth(user) != null;
@@ -91,15 +83,6 @@ public class CacheDataSource implements DataSource {
return cachedAuths.getUnchecked(user).orNull();
}
- /**
- * Method saveAuth.
- *
- * @param auth PlayerAuth
- *
- * @return boolean
- *
- * @see fr.xephi.authme.datasource.DataSource#saveAuth(PlayerAuth)
- */
@Override
public synchronized boolean saveAuth(PlayerAuth auth) {
boolean result = source.saveAuth(auth);
@@ -109,15 +92,6 @@ public class CacheDataSource implements DataSource {
return result;
}
- /**
- * Method updatePassword.
- *
- * @param auth PlayerAuth
- *
- * @return boolean
- *
- * @see fr.xephi.authme.datasource.DataSource#updatePassword(PlayerAuth)
- */
@Override
public synchronized boolean updatePassword(PlayerAuth auth) {
boolean result = source.updatePassword(auth);
@@ -137,15 +111,6 @@ public class CacheDataSource implements DataSource {
return result;
}
- /**
- * Method updateSession.
- *
- * @param auth PlayerAuth
- *
- * @return boolean
- *
- * @see fr.xephi.authme.datasource.DataSource#updateSession(PlayerAuth)
- */
@Override
public boolean updateSession(PlayerAuth auth) {
boolean result = source.updateSession(auth);
@@ -155,47 +120,20 @@ public class CacheDataSource implements DataSource {
return result;
}
- /**
- * Method updateQuitLoc.
- *
- * @param auth PlayerAuth
- *
- * @return boolean
- *
- * @see fr.xephi.authme.datasource.DataSource#updateQuitLoc(PlayerAuth)
- */
@Override
public boolean updateQuitLoc(final PlayerAuth auth) {
- boolean result = source.updateSession(auth);
+ boolean result = source.updateQuitLoc(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
}
return result;
}
- /**
- * Method getIps.
- *
- * @param ip String
- *
- * @return int
- *
- * @see fr.xephi.authme.datasource.DataSource#getIps(String)
- */
@Override
public int getIps(String ip) {
return source.getIps(ip);
}
- /**
- * Method purgeDatabase.
- *
- * @param until long
- *
- * @return int
- *
- * @see fr.xephi.authme.datasource.DataSource#purgeDatabase(long)
- */
@Override
public int purgeDatabase(long until) {
int cleared = source.purgeDatabase(until);
@@ -209,15 +147,6 @@ public class CacheDataSource implements DataSource {
return cleared;
}
- /**
- * Method autoPurgeDatabase.
- *
- * @param until long
- *
- * @return List
- *
- * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long)
- */
@Override
public List autoPurgeDatabase(long until) {
List cleared = source.autoPurgeDatabase(until);
@@ -227,15 +156,6 @@ public class CacheDataSource implements DataSource {
return cleared;
}
- /**
- * Method removeAuth.
- *
- * @param name String
- *
- * @return boolean
- *
- * @see fr.xephi.authme.datasource.DataSource#removeAuth(String)
- */
@Override
public synchronized boolean removeAuth(String name) {
name = name.toLowerCase();
@@ -246,22 +166,17 @@ public class CacheDataSource implements DataSource {
return result;
}
- /**
- * Method close.
- *
- * @see fr.xephi.authme.datasource.DataSource#close()
- */
@Override
public synchronized void close() {
- exec.shutdown();
+ try {
+ exec.shutdown();
+ exec.awaitTermination(8, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ ConsoleLogger.writeStackTrace(e);
+ }
source.close();
}
- /**
- * Method reload.
- *
- * @see fr.xephi.authme.datasource.DataSource#reload()
- */
@Override
public void reload() { // unused method
exec.execute(new Runnable() {
@@ -273,15 +188,6 @@ public class CacheDataSource implements DataSource {
});
}
- /**
- * Method updateEmail.
- *
- * @param auth PlayerAuth
- *
- * @return boolean
- *
- * @see fr.xephi.authme.datasource.DataSource#updateEmail(PlayerAuth)
- */
@Override
public synchronized boolean updateEmail(final PlayerAuth auth) {
boolean result = source.updateEmail(auth);
@@ -291,55 +197,21 @@ public class CacheDataSource implements DataSource {
return result;
}
- /**
- * Method getAllAuthsByName.
- *
- * @param auth PlayerAuth
- *
- * @return List
- *
- * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth)
- */
@Override
public synchronized List getAllAuthsByName(PlayerAuth auth) {
return source.getAllAuthsByName(auth);
}
- /**
- * Method getAllAuthsByIp.
- *
- * @param ip String
- *
- * @return List
- *
- * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String)
- */
@Override
public synchronized List getAllAuthsByIp(final String ip) {
return source.getAllAuthsByIp(ip);
}
- /**
- * Method getAllAuthsByEmail.
- *
- * @param email String
- *
- * @return List
- *
- * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String)
- */
@Override
public synchronized List getAllAuthsByEmail(final String email) {
return source.getAllAuthsByEmail(email);
}
- /**
- * Method purgeBanned.
- *
- * @param banned List
- *
- * @see fr.xephi.authme.datasource.DataSource#purgeBanned(List)
- */
@Override
public synchronized void purgeBanned(final List banned) {
exec.execute(new Runnable() {
@@ -351,39 +223,16 @@ public class CacheDataSource implements DataSource {
});
}
- /**
- * Method getType.
- *
- * @return DataSourceType
- *
- * @see fr.xephi.authme.datasource.DataSource#getType()
- */
@Override
public DataSourceType getType() {
return source.getType();
}
- /**
- * Method isLogged.
- *
- * @param user String
- *
- * @return boolean
- *
- * @see fr.xephi.authme.datasource.DataSource#isLogged(String)
- */
@Override
public boolean isLogged(String user) {
return PlayerCache.getInstance().isAuthenticated(user);
}
- /**
- * Method setLogged.
- *
- * @param user String
- *
- * @see fr.xephi.authme.datasource.DataSource#setLogged(String)
- */
@Override
public void setLogged(final String user) {
exec.execute(new Runnable() {
@@ -394,13 +243,6 @@ public class CacheDataSource implements DataSource {
});
}
- /**
- * Method setUnlogged.
- *
- * @param user String
- *
- * @see fr.xephi.authme.datasource.DataSource#setUnlogged(String)
- */
@Override
public void setUnlogged(final String user) {
exec.execute(new Runnable() {
@@ -411,11 +253,6 @@ public class CacheDataSource implements DataSource {
});
}
- /**
- * Method purgeLogged.
- *
- * @see fr.xephi.authme.datasource.DataSource#purgeLogged()
- */
@Override
public void purgeLogged() {
exec.execute(new Runnable() {
@@ -427,26 +264,11 @@ public class CacheDataSource implements DataSource {
});
}
- /**
- * Method getAccountsRegistered.
- *
- * @return int
- *
- * @see fr.xephi.authme.datasource.DataSource#getAccountsRegistered()
- */
@Override
public int getAccountsRegistered() {
return source.getAccountsRegistered();
}
- /**
- * Method updateName.
- *
- * @param oldOne String
- * @param newOne String
- *
- * @see fr.xephi.authme.datasource.DataSource#updateName(String, String)
- */
@Override
public void updateName(final String oldOne, final String newOne) {
exec.execute(new Runnable() {
@@ -458,25 +280,11 @@ public class CacheDataSource implements DataSource {
});
}
- /**
- * Method getAllAuths.
- *
- * @return List
- *
- * @see fr.xephi.authme.datasource.DataSource#getAllAuths()
- */
@Override
public List getAllAuths() {
return source.getAllAuths();
}
- /**
- * Method getLoggedPlayers.
- *
- * @return List
- *
- * @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers()
- */
@Override
public List getLoggedPlayers() {
return new ArrayList<>(PlayerCache.getInstance().getCache().values());
diff --git a/src/main/java/fr/xephi/authme/datasource/DataSource.java b/src/main/java/fr/xephi/authme/datasource/DataSource.java
index babba2ccc..2f466defc 100644
--- a/src/main/java/fr/xephi/authme/datasource/DataSource.java
+++ b/src/main/java/fr/xephi/authme/datasource/DataSource.java
@@ -79,7 +79,7 @@ public interface DataSource {
*
* @param until long
*
- * @return List
+ * @return List of String
*/
List autoPurgeDatabase(long until);
@@ -115,7 +115,7 @@ public interface DataSource {
*
* @param auth PlayerAuth
*
- * @return List
+ * @return List of String
*/
List getAllAuthsByName(PlayerAuth auth);
@@ -124,7 +124,7 @@ public interface DataSource {
*
* @param ip String
*
- * @return List * @throws Exception
+ * @return List of String * @throws Exception
*/
List getAllAuthsByIp(String ip);
@@ -133,7 +133,7 @@ public interface DataSource {
*
* @param email String
*
- * @return List * @throws Exception
+ * @return List of String * @throws Exception
*/
List getAllAuthsByEmail(String email);
@@ -153,7 +153,7 @@ public interface DataSource {
/**
* Method purgeBanned.
*
- * @param banned List
+ * @param banned List of String
*/
void purgeBanned(List banned);
@@ -207,14 +207,14 @@ public interface DataSource {
/**
* Method getAllAuths.
*
- * @return List
+ * @return List of PlayerAuth
*/
List getAllAuths();
/**
* Method getLoggedPlayers.
*
- * @return List
+ * @return List of PlayerAuth
*/
List getLoggedPlayers();
diff --git a/src/main/java/fr/xephi/authme/datasource/FlatFile.java b/src/main/java/fr/xephi/authme/datasource/FlatFile.java
index b84a84c92..4d7b4b38e 100644
--- a/src/main/java/fr/xephi/authme/datasource/FlatFile.java
+++ b/src/main/java/fr/xephi/authme/datasource/FlatFile.java
@@ -406,7 +406,7 @@ public class FlatFile implements DataSource {
*
* @param until long
*
- * @return List * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long)
+ * @return List of String * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long)
*/
@Override
public List autoPurgeDatabase(long until) {
@@ -622,7 +622,7 @@ public class FlatFile implements DataSource {
*
* @param auth PlayerAuth
*
- * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth)
+ * @return List of String * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth)
*/
@Override
public List getAllAuthsByName(PlayerAuth auth) {
@@ -659,7 +659,7 @@ public class FlatFile implements DataSource {
*
* @param ip String
*
- * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String)
+ * @return List of String * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String)
*/
@Override
public List getAllAuthsByIp(String ip) {
@@ -696,7 +696,7 @@ public class FlatFile implements DataSource {
*
* @param email String
*
- * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String)
+ * @return List of String * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String)
*/
@Override
public List getAllAuthsByEmail(String email) {
@@ -731,7 +731,7 @@ public class FlatFile implements DataSource {
/**
* Method purgeBanned.
*
- * @param banned List
+ * @param banned List of String
*
* @see fr.xephi.authme.datasource.DataSource#purgeBanned(List)
*/
@@ -876,7 +876,7 @@ public class FlatFile implements DataSource {
/**
* Method getAllAuths.
*
- * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuths()
+ * @return List of PlayerAuth * @see fr.xephi.authme.datasource.DataSource#getAllAuths()
*/
@Override
public List getAllAuths() {
@@ -928,7 +928,7 @@ public class FlatFile implements DataSource {
/**
* Method getLoggedPlayers.
*
- * @return List * @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers()
+ * @return List of PlayerAuth * @see fr.xephi.authme.datasource.DataSource#getLoggedPlayers()
*/
@Override
public List getLoggedPlayers() {
diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java
index f3870db50..876bbfa18 100644
--- a/src/main/java/fr/xephi/authme/datasource/SQLite.java
+++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java
@@ -1,11 +1,5 @@
package fr.xephi.authme.datasource;
-import fr.xephi.authme.ConsoleLogger;
-import fr.xephi.authme.cache.auth.PlayerAuth;
-import fr.xephi.authme.security.crypts.HashedPassword;
-import fr.xephi.authme.settings.Settings;
-import fr.xephi.authme.util.StringUtils;
-
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@@ -15,6 +9,12 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
+import fr.xephi.authme.ConsoleLogger;
+import fr.xephi.authme.cache.auth.PlayerAuth;
+import fr.xephi.authme.security.crypts.HashedPassword;
+import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.util.StringUtils;
+
/**
*/
public class SQLite implements DataSource {
@@ -40,7 +40,8 @@ public class SQLite implements DataSource {
/**
* Constructor for SQLite.
*
- * @throws ClassNotFoundException * @throws SQLException
+ * @throws ClassNotFoundException Exception
+ * @throws SQLException Exception
*/
public SQLite() throws ClassNotFoundException, SQLException {
this.database = Settings.getMySQLDatabase;
@@ -69,11 +70,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method connect.
- *
- * @throws ClassNotFoundException * @throws SQLException
- */
private synchronized void connect() throws ClassNotFoundException, SQLException {
Class.forName("org.sqlite.JDBC");
ConsoleLogger.info("SQLite driver loaded");
@@ -81,11 +77,6 @@ public class SQLite implements DataSource {
}
- /**
- * Method setup.
- *
- * @throws SQLException
- */
private synchronized void setup() throws SQLException {
Statement st = null;
ResultSet rs = null;
@@ -147,13 +138,6 @@ public class SQLite implements DataSource {
ConsoleLogger.info("SQLite Setup finished");
}
- /**
- * Method isAuthAvailable.
- *
- * @param user String
- *
- * @return boolean * @see fr.xephi.authme.datasource.DataSource#isAuthAvailable(String)
- */
@Override
public synchronized boolean isAuthAvailable(String user) {
PreparedStatement pst = null;
@@ -224,13 +208,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method saveAuth.
- *
- * @param auth PlayerAuth
- *
- * @return boolean * @see fr.xephi.authme.datasource.DataSource#saveAuth(PlayerAuth)
- */
@Override
public synchronized boolean saveAuth(PlayerAuth auth) {
PreparedStatement pst = null;
@@ -270,13 +247,6 @@ public class SQLite implements DataSource {
return true;
}
- /**
- * Method updatePassword.
- *
- * @param auth PlayerAuth
- *
- * @return boolean * @see fr.xephi.authme.datasource.DataSource#updatePassword(PlayerAuth)
- */
@Override
public synchronized boolean updatePassword(PlayerAuth auth) {
return updatePassword(auth.getNickname(), auth.getPassword());
@@ -309,13 +279,6 @@ public class SQLite implements DataSource {
return true;
}
- /**
- * Method updateSession.
- *
- * @param auth PlayerAuth
- *
- * @return boolean * @see fr.xephi.authme.datasource.DataSource#updateSession(PlayerAuth)
- */
@Override
public boolean updateSession(PlayerAuth auth) {
PreparedStatement pst = null;
@@ -335,13 +298,6 @@ public class SQLite implements DataSource {
return true;
}
- /**
- * Method purgeDatabase.
- *
- * @param until long
- *
- * @return int * @see fr.xephi.authme.datasource.DataSource#purgeDatabase(long)
- */
@Override
public int purgeDatabase(long until) {
PreparedStatement pst = null;
@@ -358,13 +314,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method autoPurgeDatabase.
- *
- * @param until long
- *
- * @return List * @see fr.xephi.authme.datasource.DataSource#autoPurgeDatabase(long)
- */
@Override
public List autoPurgeDatabase(long until) {
PreparedStatement pst = null;
@@ -387,13 +336,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method removeAuth.
- *
- * @param user String
- *
- * @return boolean * @see fr.xephi.authme.datasource.DataSource#removeAuth(String)
- */
@Override
public synchronized boolean removeAuth(String user) {
PreparedStatement pst = null;
@@ -410,13 +352,6 @@ public class SQLite implements DataSource {
return true;
}
- /**
- * Method updateQuitLoc.
- *
- * @param auth PlayerAuth
- *
- * @return boolean * @see fr.xephi.authme.datasource.DataSource#updateQuitLoc(PlayerAuth)
- */
@Override
public boolean updateQuitLoc(PlayerAuth auth) {
PreparedStatement pst = null;
@@ -437,13 +372,6 @@ public class SQLite implements DataSource {
return true;
}
- /**
- * Method getIps.
- *
- * @param ip String
- *
- * @return int * @see fr.xephi.authme.datasource.DataSource#getIps(String)
- */
@Override
public int getIps(String ip) {
PreparedStatement pst = null;
@@ -467,13 +395,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method updateEmail.
- *
- * @param auth PlayerAuth
- *
- * @return boolean * @see fr.xephi.authme.datasource.DataSource#updateEmail(PlayerAuth)
- */
@Override
public boolean updateEmail(PlayerAuth auth) {
PreparedStatement pst = null;
@@ -491,11 +412,6 @@ public class SQLite implements DataSource {
return true;
}
- /**
- * Method close.
- *
- * @see fr.xephi.authme.datasource.DataSource#close()
- */
@Override
public synchronized void close() {
try {
@@ -505,20 +421,10 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method reload.
- *
- * @see fr.xephi.authme.datasource.DataSource#reload()
- */
@Override
public void reload() {
}
- /**
- * Method close.
- *
- * @param st Statement
- */
private void close(Statement st) {
if (st != null) {
try {
@@ -529,11 +435,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method close.
- *
- * @param rs ResultSet
- */
private void close(ResultSet rs) {
if (rs != null) {
try {
@@ -544,13 +445,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method getAllAuthsByName.
- *
- * @param auth PlayerAuth
- *
- * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByName(PlayerAuth)
- */
@Override
public List getAllAuthsByName(PlayerAuth auth) {
PreparedStatement pst = null;
@@ -575,13 +469,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method getAllAuthsByIp.
- *
- * @param ip String
- *
- * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByIp(String)
- */
@Override
public List getAllAuthsByIp(String ip) {
PreparedStatement pst = null;
@@ -606,13 +493,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method getAllAuthsByEmail.
- *
- * @param email String
- *
- * @return List * @see fr.xephi.authme.datasource.DataSource#getAllAuthsByEmail(String)
- */
@Override
public List getAllAuthsByEmail(String email) {
PreparedStatement pst = null;
@@ -653,23 +533,11 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method getType.
- *
- * @return DataSourceType * @see fr.xephi.authme.datasource.DataSource#getType()
- */
@Override
public DataSourceType getType() {
return DataSourceType.SQLITE;
}
- /**
- * Method isLogged.
- *
- * @param user String
- *
- * @return boolean * @see fr.xephi.authme.datasource.DataSource#isLogged(String)
- */
@Override
public boolean isLogged(String user) {
PreparedStatement pst = null;
@@ -690,13 +558,6 @@ public class SQLite implements DataSource {
return false;
}
- /**
- * Method setLogged.
- *
- * @param user String
- *
- * @see fr.xephi.authme.datasource.DataSource#setLogged(String)
- */
@Override
public void setLogged(String user) {
PreparedStatement pst = null;
@@ -712,13 +573,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method setUnlogged.
- *
- * @param user String
- *
- * @see fr.xephi.authme.datasource.DataSource#setUnlogged(String)
- */
@Override
public void setUnlogged(String user) {
PreparedStatement pst = null;
@@ -735,11 +589,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method purgeLogged.
- *
- * @see fr.xephi.authme.datasource.DataSource#purgeLogged()
- */
@Override
public void purgeLogged() {
PreparedStatement pst = null;
@@ -755,11 +604,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method getAccountsRegistered.
- *
- * @return int * @see fr.xephi.authme.datasource.DataSource#getAccountsRegistered()
- */
@Override
public int getAccountsRegistered() {
int result = 0;
@@ -795,11 +639,6 @@ public class SQLite implements DataSource {
}
}
- /**
- * Method getAllAuths.
- *
- * @return List
- */
@Override
public List getAllAuths() {
List auths = new ArrayList<>();
@@ -821,11 +660,6 @@ public class SQLite implements DataSource {
return auths;
}
- /**
- * Method getLoggedPlayers.
- *
- * @return List
- */
@Override
public List getLoggedPlayers() {
List auths = new ArrayList<>();
diff --git a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java
index 42a11b3ff..2e365e932 100644
--- a/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java
+++ b/src/main/java/fr/xephi/authme/listener/AuthMePlayerListener.java
@@ -193,7 +193,7 @@ public class AuthMePlayerListener implements Listener {
}
if (Settings.isForceSurvivalModeEnabled
- && !player.hasPermission(PlayerPermission.BYPASS_FORCE_SURVIVAL.getNode())) {
+ && !player.hasPermission(PlayerPermission.BYPASS_FORCE_SURVIVAL.getNode())) {
player.setGameMode(GameMode.SURVIVAL);
}
@@ -206,9 +206,6 @@ public class AuthMePlayerListener implements Listener {
joinMessage.put(name, joinMsg);
}
- if (Settings.checkVeryGames)
- plugin.getVerygamesIp(player);
-
// Shedule login task so works after the prelogin
// (Fix found by Koolaid5000)
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@@ -222,21 +219,24 @@ public class AuthMePlayerListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onPreLogin(AsyncPlayerPreLoginEvent event) {
PlayerAuth auth = plugin.getDataSource().getAuth(event.getName());
- if (auth != null && auth.getRealName() != null && !auth.getRealName().isEmpty() &&
- !auth.getRealName().equals("Player") && !auth.getRealName().equals(event.getName())) {
- event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
- event.setKickMessage("You should join using username: " + ChatColor.AQUA + auth.getRealName() +
- ChatColor.RESET + "\nnot: " + ChatColor.RED + event.getName()); // TODO: write a better message
- return;
- }
-
- if (auth != null && auth.getRealName().equals("Player")) {
- auth.setRealName(event.getName());
- plugin.getDataSource().saveAuth(auth);
+ if (Settings.preventOtherCase && auth != null && auth.getRealName() != null) {
+ String realName = auth.getRealName();
+ if (!realName.isEmpty() && !realName.equals("Player") && !realName.equals(event.getName())) {
+ event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
+ // TODO: Add a message like : MessageKey.INVALID_NAME_CASE
+ event.setKickMessage("You should join using username: " + ChatColor.AQUA + realName +
+ ChatColor.RESET + "\nnot: " + ChatColor.RED + event.getName());
+ return;
+ }
+ if (realName.isEmpty() || realName.equals("Player")) {
+ auth.setRealName(event.getName());
+ plugin.getDataSource().saveAuth(auth);
+ }
}
+ String playerIP = event.getAddress().getHostAddress();
if (auth == null && Settings.enableProtection) {
- String countryCode = GeoLiteAPI.getCountryCode(event.getAddress().getHostAddress());
+ String countryCode = GeoLiteAPI.getCountryCode(playerIP);
if (!Settings.countriesBlacklist.isEmpty() && Settings.countriesBlacklist.contains(countryCode)) {
event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
event.setKickMessage(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
@@ -274,21 +274,26 @@ public class AuthMePlayerListener implements Listener {
// Get the permissions manager
PermissionsManager permsMan = plugin.getPermissionsManager();
- if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL
- && permsMan.hasPermission(player, PlayerPermission.IS_VIP)) {
- int playersOnline = Utils.getOnlinePlayers().size();
- if (playersOnline > plugin.getServer().getMaxPlayers()) {
- event.allow();
- } else {
- Player pl = plugin.generateKickPlayer(Utils.getOnlinePlayers());
- if (pl != null) {
- pl.kickPlayer(m.retrieveSingle(MessageKey.KICK_FOR_VIP));
+ if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL) {
+ if (permsMan.hasPermission(player, PlayerPermission.IS_VIP)) {
+ int playersOnline = Utils.getOnlinePlayers().size();
+ if (playersOnline > plugin.getServer().getMaxPlayers()) {
event.allow();
} else {
- ConsoleLogger.info("The player " + event.getPlayer().getName() + " tried to join, but the server was full");
- event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
- event.setResult(PlayerLoginEvent.Result.KICK_FULL);
+ Player pl = plugin.generateKickPlayer(Utils.getOnlinePlayers());
+ if (pl != null) {
+ pl.kickPlayer(m.retrieveSingle(MessageKey.KICK_FOR_VIP));
+ event.allow();
+ } else {
+ ConsoleLogger.info("The player " + event.getPlayer().getName() + " tried to join, but the server was full");
+ event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
+ event.setResult(PlayerLoginEvent.Result.KICK_FULL);
+ }
}
+ } else {
+ event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
+ event.setResult(PlayerLoginEvent.Result.KICK_FULL);
+ return;
}
}
@@ -296,12 +301,6 @@ public class AuthMePlayerListener implements Listener {
return;
}
- if (event.getResult() == PlayerLoginEvent.Result.KICK_FULL && !permsMan.hasPermission(player, PlayerPermission.IS_VIP)) {
- event.setKickMessage(m.retrieveSingle(MessageKey.KICK_FULL_SERVER));
- event.setResult(PlayerLoginEvent.Result.KICK_FULL);
- return;
- }
-
final String name = player.getName().toLowerCase();
boolean isAuthAvailable = plugin.getDataSource().isAuthAvailable(name);
diff --git a/src/main/java/fr/xephi/authme/listener/AuthMeServerStop.java b/src/main/java/fr/xephi/authme/listener/AuthMeServerStop.java
deleted file mode 100644
index eed3bd908..000000000
--- a/src/main/java/fr/xephi/authme/listener/AuthMeServerStop.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package fr.xephi.authme.listener;
-
-import org.bukkit.entity.Player;
-
-import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.settings.Settings;
-
-public class AuthMeServerStop extends Thread {
-
- private AuthMe plugin;
-
- public AuthMeServerStop(AuthMe plugin) {
- this.plugin = plugin;
- }
-
- public void run() {
- // TODO: add a MessageKey
- if (Settings.kickPlayersBeforeStopping) {
- plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable()
- {
- @Override
- public void run() {
- for (Player p : plugin.getServer().getOnlinePlayers()) {
- p.kickPlayer("Server is restarting");
- }
- }
- });
- }
- }
-}
diff --git a/src/main/java/fr/xephi/authme/permission/DefaultPermission.java b/src/main/java/fr/xephi/authme/permission/DefaultPermission.java
index f09de526a..24e64c742 100644
--- a/src/main/java/fr/xephi/authme/permission/DefaultPermission.java
+++ b/src/main/java/fr/xephi/authme/permission/DefaultPermission.java
@@ -25,7 +25,11 @@ public enum DefaultPermission {
this.title = title;
}
- /** Return the textual representation. */
+ /**
+ * Return the textual representation.
+ *
+ * @return String
+ */
public String getTitle() {
return title;
}
diff --git a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java
index 09b235254..9078b1ab7 100644
--- a/src/main/java/fr/xephi/authme/permission/PermissionsManager.java
+++ b/src/main/java/fr/xephi/authme/permission/PermissionsManager.java
@@ -1,10 +1,11 @@
package fr.xephi.authme.permission;
-import de.bananaco.bpermissions.api.ApiLayer;
-import de.bananaco.bpermissions.api.CalculableType;
-import fr.xephi.authme.command.CommandDescription;
-import fr.xephi.authme.util.CollectionUtils;
-import net.milkbowl.vault.permission.Permission;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
import org.anjocaido.groupmanager.GroupManager;
import org.anjocaido.groupmanager.permissions.AnjoPermissionsHandler;
import org.bukkit.Bukkit;
@@ -17,24 +18,25 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.tyrannyofheaven.bukkit.zPermissions.ZPermissionsService;
+
+import de.bananaco.bpermissions.api.ApiLayer;
+import de.bananaco.bpermissions.api.CalculableType;
+import fr.xephi.authme.command.CommandDescription;
+import fr.xephi.authme.util.CollectionUtils;
+import net.milkbowl.vault.permission.Permission;
import ru.tehkode.permissions.PermissionManager;
import ru.tehkode.permissions.PermissionUser;
import ru.tehkode.permissions.bukkit.PermissionsEx;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.logging.Logger;
-
/**
+ *
* PermissionsManager.
- *
+ *
* A permissions manager, to manage and use various permissions systems.
* This manager supports dynamic plugin hooking and various other features.
- *
+ *
* Written by Tim Visée.
- *
+ *
* @author Tim Visée, http://timvisee.com
* @version 0.2.1
*/
@@ -296,8 +298,8 @@ public class PermissionsManager implements PermissionsService {
}
Player player = (Player) sender;
- return hasPermission(player, permissionNode.getNode(), def)
- || hasPermission(player, permissionNode.getWildcardNode().getNode(), def);
+ return hasPermission(player, permissionNode.getNode(), def);
+ // || hasPermission(player, permissionNode.getWildcardNode().getNode(), def);
}
public boolean hasPermission(Player player, Iterable nodes, boolean def) {
diff --git a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
index 56656e97f..cbdac41eb 100644
--- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
+++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java
@@ -49,6 +49,10 @@ public class AsynchronousJoin {
}
public void process() {
+ if (Settings.checkVeryGames) {
+ plugin.getVerygamesIp(player);
+ }
+
if (Utils.isUnrestricted(player)) {
return;
}
@@ -58,6 +62,8 @@ public class AsynchronousJoin {
}
final String ip = plugin.getIP(player);
+
+
if (Settings.isAllowRestrictedIp && !Settings.getRestrictedIp(name, ip, player.getAddress().getHostName())) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
@@ -110,7 +116,6 @@ public class AsynchronousJoin {
});
}
}
-
placePlayerSafely(player, spawnLoc);
LimboCache.getInstance().updateLimboPlayer(player);
@@ -126,6 +131,22 @@ public class AsynchronousJoin {
}
}
+ if (Settings.isSessionsEnabled && (PlayerCache.getInstance().isAuthenticated(name) || database.isLogged(name))) {
+ if (plugin.sessions.containsKey(name)) {
+ plugin.sessions.get(name).cancel();
+ plugin.sessions.remove(name);
+ }
+ PlayerAuth auth = database.getAuth(name);
+ database.setUnlogged(name);
+ PlayerCache.getInstance().removePlayer(name);
+ if (auth != null && auth.getIp().equals(ip)) {
+ m.send(player, MessageKey.SESSION_RECONNECTION);
+ plugin.getManagement().performLogin(player, "dontneed", true);
+ return;
+ } else if (Settings.sessionExpireOnIpChange) {
+ m.send(player, MessageKey.SESSION_EXPIRED);
+ }
+ }
} else {
if (!Settings.unRegisteredGroup.isEmpty()) {
Utils.setGroup(player, Utils.GroupType.UNREGISTERED);
@@ -179,7 +200,7 @@ public class AsynchronousJoin {
if (Settings.applyBlindEffect) {
int blindTimeOut;
// Allow infinite blindness effect
- if(timeOut <= 0) {
+ if (timeOut <= 0) {
blindTimeOut = 99999;
} else {
blindTimeOut = timeOut;
@@ -196,23 +217,6 @@ public class AsynchronousJoin {
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id);
}
- if (Settings.isSessionsEnabled && isAuthAvailable && (PlayerCache.getInstance().isAuthenticated(name) || database.isLogged(name))) {
- if (plugin.sessions.containsKey(name)) {
- plugin.sessions.get(name).cancel();
- plugin.sessions.remove(name);
- }
- PlayerAuth auth = database.getAuth(name);
- database.setUnlogged(name);
- PlayerCache.getInstance().removePlayer(name);
- if (auth != null && auth.getIp().equals(ip)) {
- m.send(player, MessageKey.SESSION_RECONNECTION);
- plugin.getManagement().performLogin(player, "dontneed", true);
- return;
- } else if (Settings.sessionExpireOnIpChange) {
- m.send(player, MessageKey.SESSION_EXPIRED);
- }
- }
-
String[] msg;
if (isAuthAvailable) {
msg = m.retrieve(MessageKey.LOGIN_MESSAGE);
diff --git a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
index 8297224bf..9b911da17 100644
--- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
+++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java
@@ -33,6 +33,7 @@ public class AsynchronousLogin {
private final AuthMe plugin;
private final DataSource database;
private final Messages m;
+ private final String ip;
/**
* Constructor for AsynchronousLogin.
@@ -52,10 +53,7 @@ public class AsynchronousLogin {
this.forceLogin = forceLogin;
this.plugin = plugin;
this.database = data;
- }
-
- protected String getIP() {
- return plugin.getIP(player);
+ this.ip = plugin.getIP(player);
}
protected boolean needsCaptcha() {
@@ -87,7 +85,9 @@ public class AsynchronousLogin {
m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
return null;
}
- if (!database.isAuthAvailable(name)) {
+
+ PlayerAuth pAuth = database.getAuth(name);
+ if (pAuth == null) {
m.send(player, MessageKey.USER_NOT_REGISTERED);
if (LimboCache.getInstance().hasLimboPlayer(name)) {
LimboCache.getInstance().getLimboPlayer(name).getMessageTaskId().cancel();
@@ -97,43 +97,45 @@ public class AsynchronousLogin {
} else {
msg = m.retrieve(MessageKey.REGISTER_MESSAGE);
}
- BukkitTask msgT = Bukkit.getScheduler().runTaskAsynchronously(plugin, new MessageTask(plugin, name, msg, Settings.getWarnMessageInterval));
+ BukkitTask msgT = Bukkit.getScheduler().runTaskAsynchronously(plugin,
+ new MessageTask(plugin, name, msg, Settings.getWarnMessageInterval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT);
}
return null;
}
- if (Settings.getMaxLoginPerIp > 0 && !plugin.getPermissionsManager().hasPermission(player, PlayerPermission.ALLOW_MULTIPLE_ACCOUNTS) && !getIP().equalsIgnoreCase("127.0.0.1") && !getIP().equalsIgnoreCase("localhost")) {
- if (plugin.isLoggedIp(name, getIP())) {
- m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
- return null;
- }
- }
- PlayerAuth pAuth = database.getAuth(name);
- if (pAuth == null) {
- m.send(player, MessageKey.USER_NOT_REGISTERED);
- return null;
- }
+
if (!Settings.getMySQLColumnGroup.isEmpty() && pAuth.getGroupId() == Settings.getNonActivatedGroup) {
m.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
return null;
}
- if (Settings.preventOtherCase && !player.getName().equals(pAuth.getRealName())) {
- // TODO: Add a message like : MessageKey.INVALID_NAME_CASE
- m.send(player, MessageKey.USERNAME_ALREADY_ONLINE_ERROR);
- return null;
+ if (Settings.getMaxLoginPerIp > 0
+ && !plugin.getPermissionsManager().hasPermission(player, PlayerPermission.ALLOW_MULTIPLE_ACCOUNTS)
+ && !ip.equalsIgnoreCase("127.0.0.1") && !ip.equalsIgnoreCase("localhost")) {
+ if (plugin.isLoggedIp(name, ip)) {
+ m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
+ return null;
+ }
}
+
AuthMeAsyncPreLoginEvent event = new AuthMeAsyncPreLoginEvent(player);
Bukkit.getServer().getPluginManager().callEvent(event);
- if (!event.canLogin())
+ if (!event.canLogin()) {
return null;
+ }
return pAuth;
}
public void process() {
PlayerAuth pAuth = preAuth();
- if (pAuth == null || needsCaptcha())
+ if (pAuth == null || needsCaptcha()) {
return;
+ }
+
+ if (pAuth.getIp().equals("127.0.0.1") && !pAuth.getIp().equals(ip)) {
+ pAuth.setIp(ip);
+ database.saveAuth(pAuth);
+ }
String email = pAuth.getEmail();
boolean passwordVerified = forceLogin || plugin.getPasswordSecurity()
@@ -143,7 +145,7 @@ public class AsynchronousLogin {
PlayerAuth auth = PlayerAuth.builder()
.name(name)
.realName(realName)
- .ip(getIP())
+ .ip(ip)
.lastLogin(new Date().getTime())
.email(email)
.password(pAuth.getPassword())
@@ -184,14 +186,16 @@ public class AsynchronousLogin {
// task, we schedule it in the end
// so that we can be sure, and have not to care if it might be
// processed in other order.
- ProcessSyncronousPlayerLogin syncronousPlayerLogin = new ProcessSyncronousPlayerLogin(player, plugin, database);
- if (syncronousPlayerLogin.getLimbo() != null) {
- if (syncronousPlayerLogin.getLimbo().getTimeoutTaskId() != null)
- syncronousPlayerLogin.getLimbo().getTimeoutTaskId().cancel();
- if (syncronousPlayerLogin.getLimbo().getMessageTaskId() != null)
- syncronousPlayerLogin.getLimbo().getMessageTaskId().cancel();
+ ProcessSyncPlayerLogin syncPlayerLogin = new ProcessSyncPlayerLogin(player, plugin, database);
+ if (syncPlayerLogin.getLimbo() != null) {
+ if (syncPlayerLogin.getLimbo().getTimeoutTaskId() != null) {
+ syncPlayerLogin.getLimbo().getTimeoutTaskId().cancel();
+ }
+ if (syncPlayerLogin.getLimbo().getMessageTaskId() != null) {
+ syncPlayerLogin.getLimbo().getMessageTaskId().cancel();
+ }
}
- Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, syncronousPlayerLogin);
+ Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, syncPlayerLogin);
} else if (player.isOnline()) {
if (!Settings.noConsoleSpam)
ConsoleLogger.info(realName + " used the wrong password");
diff --git a/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java b/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java
similarity index 96%
rename from src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java
rename to src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java
index c4562d506..27c09174e 100644
--- a/src/main/java/fr/xephi/authme/process/login/ProcessSyncronousPlayerLogin.java
+++ b/src/main/java/fr/xephi/authme/process/login/ProcessSyncPlayerLogin.java
@@ -26,7 +26,7 @@ import fr.xephi.authme.util.Utils.GroupType;
/**
*/
-public class ProcessSyncronousPlayerLogin implements Runnable {
+public class ProcessSyncPlayerLogin implements Runnable {
private final LimboPlayer limbo;
private final Player player;
@@ -38,14 +38,14 @@ public class ProcessSyncronousPlayerLogin implements Runnable {
private final JsonCache playerCache;
/**
- * Constructor for ProcessSyncronousPlayerLogin.
+ * Constructor for ProcessSyncPlayerLogin.
*
* @param player Player
* @param plugin AuthMe
* @param data DataSource
*/
- public ProcessSyncronousPlayerLogin(Player player, AuthMe plugin,
- DataSource data) {
+ public ProcessSyncPlayerLogin(Player player, AuthMe plugin,
+ DataSource data) {
this.plugin = plugin;
this.database = data;
this.pm = plugin.getServer().getPluginManager();
diff --git a/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java b/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java
index 42c633afc..2a3a5d3e0 100644
--- a/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java
+++ b/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java
@@ -93,6 +93,7 @@ public class AsynchronousQuit {
database.setUnlogged(name);
}
+ plugin.realIp.remove(name);
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange));
}
}
diff --git a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java
index 50572eb61..6d9ab98dc 100644
--- a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java
+++ b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java
@@ -3,9 +3,8 @@ package fr.xephi.authme.security;
import fr.xephi.authme.security.crypts.EncryptionMethod;
/**
- * The list of hash algorithms supported by AuthMe. The implementing class must define a public
- * constructor which takes either no arguments, or a DataSource object (when the salt is stored
- * separately, writes to the database are necessary).
+ * The list of hash algorithms supported by AuthMe. The linked {@link EncryptionMethod} implementation
+ * must be able to be instantiated with the default constructor.
*/
public enum HashAlgorithm {
diff --git a/src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java b/src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java
index eb8c717a9..a8ea653bb 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/BCRYPT.java
@@ -15,6 +15,7 @@ package fr.xephi.authme.security.crypts;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.security.crypts.description.HasSalt;
+import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.SaltType;
import fr.xephi.authme.security.crypts.description.Usage;
@@ -108,7 +109,6 @@ public class BCRYPT implements EncryptionMethod {
*
* @throws IllegalArgumentException if the length is invalid
*/
-
private static String encode_base64(byte d[], int len)
throws IllegalArgumentException {
int off = 0;
diff --git a/src/main/java/fr/xephi/authme/security/crypts/CRAZYCRYPT1.java b/src/main/java/fr/xephi/authme/security/crypts/CRAZYCRYPT1.java
index 269c1365e..cd8af9249 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/CRAZYCRYPT1.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/CRAZYCRYPT1.java
@@ -10,8 +10,6 @@ import fr.xephi.authme.security.crypts.description.HasSalt;
import java.nio.charset.Charset;
import java.security.MessageDigest;
-@Recommendation(Usage.DO_NOT_USE)
-@HasSalt(SaltType.USERNAME)
public class CRAZYCRYPT1 extends UsernameSaltMethod {
private static final char[] CRYPTCHARS =
diff --git a/src/main/java/fr/xephi/authme/security/crypts/IPB3.java b/src/main/java/fr/xephi/authme/security/crypts/IPB3.java
index 85789b881..4abfe5d45 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/IPB3.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/IPB3.java
@@ -8,7 +8,7 @@ import fr.xephi.authme.security.crypts.description.Usage;
import static fr.xephi.authme.security.HashUtils.md5;
-@Recommendation(Usage.DO_NOT_USE)
+@Recommendation(Usage.ACCEPTABLE)
@HasSalt(value = SaltType.TEXT, length = 5)
public class IPB3 extends SeparateSaltMethod {
diff --git a/src/main/java/fr/xephi/authme/security/crypts/MYBB.java b/src/main/java/fr/xephi/authme/security/crypts/MYBB.java
index 97418640c..555f3213a 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/MYBB.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/MYBB.java
@@ -1,9 +1,15 @@
package fr.xephi.authme.security.crypts;
import fr.xephi.authme.security.RandomString;
+import fr.xephi.authme.security.crypts.description.HasSalt;
+import fr.xephi.authme.security.crypts.description.Recommendation;
+import fr.xephi.authme.security.crypts.description.SaltType;
+import fr.xephi.authme.security.crypts.description.Usage;
import static fr.xephi.authme.security.HashUtils.md5;
+@Recommendation(Usage.ACCEPTABLE)
+@HasSalt(value = SaltType.TEXT, length = 8)
public class MYBB extends SeparateSaltMethod {
@Override
diff --git a/src/main/java/fr/xephi/authme/security/crypts/WBB3.java b/src/main/java/fr/xephi/authme/security/crypts/WBB3.java
index 6cc123005..28e975856 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/WBB3.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/WBB3.java
@@ -1,9 +1,15 @@
package fr.xephi.authme.security.crypts;
import fr.xephi.authme.security.RandomString;
+import fr.xephi.authme.security.crypts.description.HasSalt;
+import fr.xephi.authme.security.crypts.description.Recommendation;
+import fr.xephi.authme.security.crypts.description.SaltType;
+import fr.xephi.authme.security.crypts.description.Usage;
import static fr.xephi.authme.security.HashUtils.sha1;
+@Recommendation(Usage.ACCEPTABLE)
+@HasSalt(value = SaltType.TEXT, length = 40)
public class WBB3 extends SeparateSaltMethod {
@Override
diff --git a/src/main/java/fr/xephi/authme/security/crypts/WHIRLPOOL.java b/src/main/java/fr/xephi/authme/security/crypts/WHIRLPOOL.java
index 0169d1927..72d8e8fb6 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/WHIRLPOOL.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/WHIRLPOOL.java
@@ -241,8 +241,9 @@ public class WHIRLPOOL extends UnsaltedMethod {
*
* @param source plaintext data to hash.
* @param sourceBits how many bits of plaintext to process.
- *
- * This method maintains the invariant: bufferBits < 512
+ *
+ * This method maintains the invariant: bufferBits < 512
+ *
*/
public void NESSIEadd(byte[] source, long sourceBits) {
/*
@@ -322,10 +323,12 @@ public class WHIRLPOOL extends UnsaltedMethod {
}
/**
+ *
* Get the hash value from the hashing state.
- *
- * This method uses the invariant: bufferBits < 512
- *
+ *
+ *
+ * This method uses the invariant: bufferBits < 512
+ *
* @param digest byte[]
*/
public void NESSIEfinalize(byte[] digest) {
@@ -367,7 +370,7 @@ public class WHIRLPOOL extends UnsaltedMethod {
* Delivers string input data to the hashing algorithm.
*
* @param source plaintext data to hash (ASCII text string).
- * This method maintains the invariant: bufferBits < 512
+ * This method maintains the invariant: bufferBits < 512
*/
public void NESSIEadd(String source) {
if (source.length() > 0) {
diff --git a/src/main/java/fr/xephi/authme/security/crypts/description/AsciiRestricted.java b/src/main/java/fr/xephi/authme/security/crypts/description/AsciiRestricted.java
index f515717e7..bf179fff2 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/description/AsciiRestricted.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/description/AsciiRestricted.java
@@ -6,7 +6,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Denotes an encryption algorithm that is restricted to the ASCII charset.
+ * Denotes a hashing algorithm that is restricted to the ASCII charset.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
diff --git a/src/main/java/fr/xephi/authme/security/crypts/description/HasSalt.java b/src/main/java/fr/xephi/authme/security/crypts/description/HasSalt.java
index 1baf1e196..0723a4ddb 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/description/HasSalt.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/description/HasSalt.java
@@ -13,10 +13,18 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface HasSalt {
- /** The type of the salt. */
+ /**
+ * The type of the salt.
+ *
+ * @return The salt type
+ */
SaltType value();
- /** For text salts, the length of the salt. */
+ /**
+ * For text salts, the length of the salt.
+ *
+ * @return The length of the salt the algorithm uses, or 0 if not defined or not applicable.
+ */
int length() default 0;
}
diff --git a/src/main/java/fr/xephi/authme/security/crypts/description/Recommendation.java b/src/main/java/fr/xephi/authme/security/crypts/description/Recommendation.java
index f37c3eac3..4b832a681 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/description/Recommendation.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/description/Recommendation.java
@@ -6,13 +6,19 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Annotation to mark a hash algorithm with the usage recommendation, see {@link Usage}.
+ * Annotation to mark a hash algorithm with the usage recommendation.
+ *
+ * @see Usage
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Recommendation {
- /** The recommendation for using the hash algorithm. */
+ /**
+ * The recommendation for using the hash algorithm.
+ *
+ * @return The recommended usage
+ */
Usage value();
}
diff --git a/src/main/java/fr/xephi/authme/security/crypts/description/SaltType.java b/src/main/java/fr/xephi/authme/security/crypts/description/SaltType.java
index 7d6b225ca..40b923fa9 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/description/SaltType.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/description/SaltType.java
@@ -8,7 +8,7 @@ public enum SaltType {
/** Random, newly generated text. */
TEXT,
- /** Salt is based on the username, including variations and repetitions. */
+ /** Salt is based on the username, including variations and repetitions thereof. */
USERNAME,
/** No salt. */
diff --git a/src/main/java/fr/xephi/authme/security/crypts/description/Usage.java b/src/main/java/fr/xephi/authme/security/crypts/description/Usage.java
index ecf37a980..c11c335ac 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/description/Usage.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/description/Usage.java
@@ -2,6 +2,12 @@ package fr.xephi.authme.security.crypts.description;
/**
* Usage recommendation that can be provided for a hash algorithm.
+ *
+ * Use the following rules of thumb:
+ *
+ *
Hashes using MD5 may be {@link #ACCEPTABLE} but never {@link #RECOMMENDED}.
+ *
Hashes using no salt or one based on the username should be {@link #DO_NOT_USE}.
+ *
*/
public enum Usage {
diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/MacBasedPRF.java b/src/main/java/fr/xephi/authme/security/pbkdf2/MacBasedPRF.java
index 5b0268c18..88ff11bfc 100644
--- a/src/main/java/fr/xephi/authme/security/pbkdf2/MacBasedPRF.java
+++ b/src/main/java/fr/xephi/authme/security/pbkdf2/MacBasedPRF.java
@@ -1,15 +1,16 @@
package fr.xephi.authme.security.pbkdf2;
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
/**
- * Default PRF implementation based on standard javax.crypt.Mac mechanisms.
*
- *
+ * Default PRF implementation based on standard javax.crypt.Mac mechanisms.
+ *
*
* A free Java implementation of Password Based Key Derivation Function 2 as
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2.java
index d1dab3025..59bc96df2 100644
--- a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2.java
+++ b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2.java
@@ -75,7 +75,7 @@ public interface PBKDF2 {
/**
* Allow setting of configured parameters.
*
- * @param parameters
+ * @param parameters PBKDF2Parameters
*/
void setParameters(PBKDF2Parameters parameters);
diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Engine.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Engine.java
index c78f786ad..d32b8752d 100644
--- a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Engine.java
+++ b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Engine.java
@@ -8,20 +8,17 @@ import java.security.SecureRandom;
/**
*
dkLen intended length in octets of the derived key, a positive integer,
* at most (2^32 - 1) * hLen
*
- *
- *
* Output:
*
*
DK derived key, a dkLen-octet string
*
*
- *
- *
* A free Java implementation of Password Based Key Derivation Function 2 as
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
*
@@ -115,13 +108,14 @@ public class PBKDF2Engine implements PBKDF2 {
* ISO-8559-1 encoding. Output result as
* "Salt:iteration-count:PBKDF2" with binary data in hexadecimal
* encoding.
- *
+ *
* Example: Password "password" (without the quotes) leads to
* 48290A0B96C426C3:1000:973899B1D4AFEB3ED371060D0797E0EE0142BD04
- *
+ *
* @param args Supply the password as argument.
*
- * @throws IOException * @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
+ * @throws IOException an ioexception occured
+ * @throws NoSuchAlgorithmException a NoSuchAlgorithmException occured
*/
public static void main(String[] args)
throws IOException, NoSuchAlgorithmException {
@@ -266,8 +260,8 @@ public class PBKDF2Engine implements PBKDF2 {
/**
* Integer division with ceiling function.
*
- * @param a
- * @param b
+ * @param a Integer
+ * @param b Integer
*
* @return ceil(a/b) * @see RFC 2898 5.2 Step
* 2.
@@ -288,7 +282,7 @@ public class PBKDF2Engine implements PBKDF2 {
* @param prf Pseudo Random Function
* @param S Salt as array of bytes
* @param c Iteration count
- * @param blockIndex
+ * @param blockIndex Integer
*
* @see RFC 2898 5.2 Step
* 3.
@@ -314,8 +308,8 @@ public class PBKDF2Engine implements PBKDF2 {
* Block-Xor. Xor source bytes into destination byte buffer. Destination
* buffer must be same length or less than source buffer.
*
- * @param dest
- * @param src
+ * @param dest byte array
+ * @param src byte array
*/
protected void xor(byte[] dest, byte[] src) {
for (int i = 0; i < dest.length; i++) {
@@ -326,9 +320,9 @@ public class PBKDF2Engine implements PBKDF2 {
/**
* Four-octet encoding of the integer i, most significant octet first.
*
- * @param dest
- * @param offset
- * @param i
+ * @param dest byte array
+ * @param offset Integer
+ * @param i Integer
*
* @see RFC 2898 5.2 Step
* 3.
diff --git a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Parameters.java b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Parameters.java
index b7b158a0c..04abaa9f8 100644
--- a/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Parameters.java
+++ b/src/main/java/fr/xephi/authme/security/pbkdf2/PBKDF2Parameters.java
@@ -5,8 +5,6 @@ package fr.xephi.authme.security.pbkdf2;
* Parameter data holder for PBKDF2 configuration.
*
*
- *
- *
* A free Java implementation of Password Based Key Derivation Function 2 as
* defined by RFC 2898. Copyright (c) 2007 Matthias Gärtner
*
diff --git a/src/main/java/fr/xephi/authme/settings/OtherAccounts.java b/src/main/java/fr/xephi/authme/settings/OtherAccounts.java
index 063e6af60..6e2796a32 100644
--- a/src/main/java/fr/xephi/authme/settings/OtherAccounts.java
+++ b/src/main/java/fr/xephi/authme/settings/OtherAccounts.java
@@ -1,13 +1,13 @@
package fr.xephi.authme.settings;
-import org.bukkit.Bukkit;
-import org.bukkit.entity.Player;
-
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
/**
* @author Xephi59
* @version $Revision: 1.0 $
@@ -88,7 +88,7 @@ public class OtherAccounts extends CustomConfiguration {
*
* @param uuid UUID
*
- * @return List
+ * @return StringList
*/
public List getAllPlayersByUUID(UUID uuid) {
return this.getStringList(uuid.toString());
diff --git a/src/main/java/fr/xephi/authme/settings/Settings.java b/src/main/java/fr/xephi/authme/settings/Settings.java
index 6080d45eb..cfb28f75e 100644
--- a/src/main/java/fr/xephi/authme/settings/Settings.java
+++ b/src/main/java/fr/xephi/authme/settings/Settings.java
@@ -1,32 +1,27 @@
package fr.xephi.authme.settings;
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+import fr.xephi.authme.AuthMe;
+import fr.xephi.authme.ConsoleLogger;
+import fr.xephi.authme.datasource.DataSource;
+import fr.xephi.authme.datasource.DataSource.DataSourceType;
+import fr.xephi.authme.security.HashAlgorithm;
+import fr.xephi.authme.util.Wrapper;
+import org.bukkit.configuration.file.YamlConfiguration;
+
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.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.Files;
-
-import fr.xephi.authme.AuthMe;
-import fr.xephi.authme.ConsoleLogger;
-import fr.xephi.authme.datasource.DataSource;
-import fr.xephi.authme.datasource.DataSource.DataSourceType;
-import fr.xephi.authme.security.HashAlgorithm;
-import fr.xephi.authme.util.Wrapper;
-
/**
*/
public final class Settings {
@@ -122,7 +117,7 @@ public final class Settings {
/**
* Method reload.
*
- * @throws Exception
+ * @throws Exception if something went wrong
*/
public static void reload() throws Exception {
plugin.getLogger().info("Loading Configuration File...");
@@ -141,7 +136,6 @@ public final class Settings {
messageFile = new File(PLUGIN_FOLDER, "messages" + File.separator + "messages_" + messagesLanguage + ".yml");
}
-
public static void loadVariables() {
helpHeader = configFile.getString("settings.helpHeader", "AuthMeReloaded");
messagesLanguage = checkLang(configFile.getString("settings.messagesLanguage", "en").toLowerCase());
@@ -311,35 +305,22 @@ public final class Settings {
}
private static String loadEmailText() {
- if (!EMAIL_FILE.exists())
- saveDefaultEmailText();
- StringBuilder str = new StringBuilder();
- try {
- BufferedReader in = new BufferedReader(new FileReader(EMAIL_FILE));
- String s;
- while ((s = in.readLine()) != null)
- str.append(s);
- in.close();
- } catch (IOException ignored) {
+ if (!EMAIL_FILE.exists()) {
+ plugin.saveResource("email.html", false);
}
- return str.toString();
- }
-
- private static void saveDefaultEmailText() {
- InputStream file = plugin.getResource("email.html");
- StringBuilder str = new StringBuilder();
try {
- BufferedReader in = new BufferedReader(new InputStreamReader(file, Charset.forName("utf-8")));
- String s;
- while ((s = in.readLine()) != null)
- str.append(s);
- in.close();
- Files.touch(EMAIL_FILE);
- Files.write(str.toString(), EMAIL_FILE, Charsets.UTF_8);
- } catch (Exception ignored) {
+ return Files.toString(EMAIL_FILE, Charsets.UTF_8);
+ } catch (IOException e) {
+ ConsoleLogger.showError(e.getMessage());
+ ConsoleLogger.writeStackTrace(e);
+ return "";
}
}
+ /**
+ * @param key the key to set
+ * @param value the value to set
+ */
public static void setValue(String key, Object value) {
instance.set(key, value);
save();
@@ -380,8 +361,9 @@ public final class Settings {
* return false if ip and name doesn't match with player that join the
* server, so player has a restricted access
*
- * @param name String
- * @param ip String
+ * @param name String
+ * @param ip String
+ * @param domain String
*
* @return boolean
*/
@@ -396,14 +378,12 @@ public final class Settings {
String testIp = args[1];
if (testName.equalsIgnoreCase(name)) {
nameFound = true;
- if (ip != null)
- {
+ if (ip != null) {
if (testIp.equalsIgnoreCase(ip)) {
trueOnce = true;
}
}
- if (domain != null)
- {
+ if (domain != null) {
if (testIp.equalsIgnoreCase(domain)) {
trueOnce = true;
}
@@ -737,10 +717,9 @@ public final class Settings {
changes = true;
}
- if (!contains("settings.preventOtherCase"))
- {
- set("settings.preventOtherCase", false);
- changes = true;
+ if (!contains("settings.preventOtherCase")) {
+ set("settings.preventOtherCase", false);
+ changes = true;
}
if (contains("Email.mailText")) {
@@ -749,15 +728,14 @@ public final class Settings {
}
if (!contains("Security.stop.kickPlayersBeforeStopping")) {
- set("Security.stop.kickPlayersBeforeStopping", true);
- changes = true;
+ set("Security.stop.kickPlayersBeforeStopping", true);
+ changes = true;
}
if (!contains("Email.emailOauth2Token"))
- set("Email.emailOauth2Token", "");
+ set("Email.emailOauth2Token", "");
- if (!contains("Hook.sendPlayerTo"))
- {
+ if (!contains("Hook.sendPlayerTo")) {
set("Hooks.sendPlayerTo", "");
changes = true;
}
@@ -768,11 +746,21 @@ public final class Settings {
}
}
+ /**
+ * @param path
+ *
+ * @return
+ */
private static boolean contains(String path) {
return configFile.contains(path);
}
// public because it's used in AuthMe at one place
+
+ /**
+ * @param path String
+ * @param value String
+ */
public void set(String path, Object value) {
configFile.set(path, value);
}
diff --git a/src/main/java/fr/xephi/authme/util/CollectionUtils.java b/src/main/java/fr/xephi/authme/util/CollectionUtils.java
index 101ad968f..5c3eaa7f7 100644
--- a/src/main/java/fr/xephi/authme/util/CollectionUtils.java
+++ b/src/main/java/fr/xephi/authme/util/CollectionUtils.java
@@ -15,6 +15,8 @@ public final class CollectionUtils {
/**
* Get a range from a list based on start and count parameters in a safe way.
*
+ * @param element
+ * @param list The List
* @param start The start index
* @param count The number of elements to add
*
@@ -34,6 +36,8 @@ public final class CollectionUtils {
/**
* Get all elements from a list starting from the given index.
*
+ * @param element
+ * @param list The List
* @param start The start index
*
* @return The sublist of all elements from index {@code start} and on; empty list
@@ -46,6 +50,11 @@ public final class CollectionUtils {
return getRange(list, start, list.size() - start);
}
+ /**
+ * @param element
+ * @param coll Collection
+ * @return boolean Boolean
+ */
public static boolean isEmpty(Collection coll) {
return coll == null || coll.isEmpty();
}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index ec382c7c9..69e954e36 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -45,120 +45,144 @@ commands:
usage: /converter
permissions:
authme.admin.*:
- description: Gives access to all authme admin commands
- children:
- authme.admin.reload: true
- authme.admin.register: true
- authme.admin.changepassword: true
- authme.admin.unregister: true
- authme.admin.purge: true
- authme.seeOtherAccounts: true # This isn't a child of the admin section! Probably doesn't work.
- authme.admin.lastlogin: true
- authme.admin.getemail: true
- authme.admin.chgemail: true
- authme.admin.purgelastpos: true
- authme.admin.switchantibot: true
- authme.bypassantibot: true # This isn't a child of the admin section! Probably doesn't work.
- authme.admin.getip: true
- authme.admin.converter: true
- authme.admin.resetposition: true
- authme.admin.forcelogin: true
- authme.register:
- description: Register an account
- default: true
- authme.login:
- description: Login into a account
- default: true
- authme.changepassword:
- description: Change password of a account
- default: true
- authme.logout:
- description: Logout
- default: true
- authme.email:
- description: Email
- default: true
- authme.allow2accounts:
- description: allow more accounts for same ip
- default: false
- authme.seeOtherAccounts:
- description: display other accounts about a player when he logs in
- default: false
- authme.unregister:
- description: unregister your account
- default: true
- authme.admin.reload:
- description: AuthMe reload commands
- default: op
+ description: Give access to all admin commands.
+ children:
+ authme.admin.accounts: true
+ authme.admin.changemail: true
+ authme.admin.changepassword: true
+ authme.admin.converter: true
+ authme.admin.firstspawn: true
+ authme.admin.forcelogin: true
+ authme.admin.getemail: true
+ authme.admin.getip: true
+ authme.admin.lastlogin: true
+ authme.admin.purge: true
+ authme.admin.purgebannedplayers: true
+ authme.admin.purgelastpos: true
+ authme.admin.register: true
+ authme.admin.reload: true
+ authme.admin.setfirstspawn: true
+ authme.admin.setspawn: true
+ authme.admin.spawn: true
+ authme.admin.switchantibot: true
+ authme.admin.unregister: true
authme.admin.register:
- description: AuthMe register command
- default: op
- authme.admin.changepassword:
- description: AuthMe changepassword command
+ description: Administrator command to register a new user.
default: op
authme.admin.unregister:
- description: AuthMe unregister command
- default: op
- authme.admin.purge:
- description: AuthMe unregister command
- default: op
- authme.admin.lastlogin:
- description: Get last login date about a player
- default: op
- authme.admin.getemail:
- description: Get last email about a player
- default: op
- authme.admin.chgemail:
- description: Change a player email
- default: op
- authme.admin.accounts:
- description: Display Players Accounts
- default: op
- authme.captcha:
- description: Captcha
- default: true
- authme.admin.setspawn:
- description: Set the AuthMe spawn point
- default: op
- authme.admin.spawn:
- description: Teleport to AuthMe spawn point
- default: op
- authme.vip:
- description: Allow vip slot when the server is full
- default: op
- authme.admin.purgebannedplayers:
- description: Purge banned players
- default: op
- authme.bypassforcesurvival:
- description: Bypass all ForceSurvival features
- default: false
- authme.admin.purgelastpos:
- description: Purge last pos of players
- default: op
- authme.admin.switchantibot:
- description: Switch AntiBot mode on/off
- default: op
- authme.bypassantibot:
- description: Bypass the AntiBot check
- default: op
- authme.admin.setfirstspawn:
- description: Set the AuthMe First Spawn Point
- default: op
- authme.admin.firstspawn:
- description: Teleport to AuthMe First Spawn Point
- default: op
- authme.admin.getip:
- description: Get IP from a player ( fake and real )
- default: op
- authme.admin.converter:
- description: Allow /converter command
- default: op
- authme.admin.resetposition:
- description: Reset last position for a player
+ description: Administrator command to unregister an existing user.
default: op
authme.admin.forcelogin:
- description: Force login for that player
+ description: Administrator command to force-login an existing user.
default: op
- authme.canbeforced:
- description: Can this player be forced to login
+ authme.admin.changepassword:
+ description: Administrator command to change the password of a user.
+ default: op
+ authme.admin.lastlogin:
+ description: Administrator command to see the last login date and time of a user.
+ default: op
+ authme.admin.accounts:
+ description: Administrator command to see all accounts associated with a user.
+ default: op
+ authme.admin.getemail:
+ description: Administrator command to get the email address of a user, if set.
+ default: op
+ authme.admin.changemail:
+ description: Administrator command to set or change the email address of a user.
+ default: op
+ authme.admin.getip:
+ description: Administrator command to get the last known IP of a user.
+ default: op
+ authme.admin.spawn:
+ description: Administrator command to teleport to the AuthMe spawn.
+ default: op
+ authme.admin.setspawn:
+ description: Administrator command to set the AuthMe spawn.
+ default: op
+ authme.admin.firstspawn:
+ description: Administrator command to teleport to the first AuthMe spawn.
+ default: op
+ authme.admin.setfirstspawn:
+ description: Administrator command to set the first AuthMe spawn.
+ default: op
+ authme.admin.purge:
+ description: Administrator command to purge old user data.
+ default: op
+ authme.admin.purgelastpos:
+ description: Administrator command to purge the last position of a user.
+ default: op
+ authme.admin.purgebannedplayers:
+ description: Administrator command to purge all data associated with banned players.
+ default: op
+ authme.admin.switchantibot:
+ description: Administrator command to toggle the AntiBot protection status.
+ default: op
+ authme.admin.converter:
+ description: Administrator command to convert old or other data to AuthMe data.
+ default: op
+ authme.admin.reload:
+ description: Administrator command to reload the plugin configuration.
+ default: op
+ authme.player.*:
+ description: Permission to use all player (non-admin) commands.
+ children:
+ authme.player.allow2accounts: true
+ authme.player.bypassantibot: true
+ authme.player.bypassforcesurvival: true
+ authme.player.canbeforced: true
+ authme.player.captcha: true
+ authme.player.changepassword: true
+ authme.player.email.add: true
+ authme.player.email.change: true
+ authme.player.email.recover: true
+ authme.player.login: true
+ authme.player.logout: true
+ authme.player.register: true
+ authme.player.seeotheraccounts: true
+ authme.player.unregister: true
+ authme.player.vip: true
+ authme.player.bypassantibot:
+ description: Permission node to bypass AntiBot protection.
+ default: false
+ authme.player.vip:
+ description: Permission node to identify VIP users.
+ default: false
+ authme.player.login:
+ description: Command permission to login.
default: true
+ authme.player.logout:
+ description: Command permission to logout.
+ default: true
+ authme.player.register:
+ description: Command permission to register.
+ default: true
+ authme.player.unregister:
+ description: Command permission to unregister.
+ default: true
+ authme.player.changepassword:
+ description: Command permission to change the password.
+ default: true
+ authme.player.email.add:
+ description: Command permission to add an email address.
+ default: false
+ authme.player.email.change:
+ description: Command permission to change the email address.
+ default: false
+ authme.player.email.recover:
+ description: Command permission to recover an account using it's email address.
+ default: false
+ authme.player.captcha:
+ description: Command permission to use captcha.
+ default: false
+ authme.player.canbeforced:
+ description: Permission for users a login can be forced to.
+ default: false
+ authme.player.bypassforcesurvival:
+ description: Permission for users to bypass force-survival mode.
+ default: false
+ authme.player.allow2accounts:
+ description: Permission for users to allow two accounts.
+ default: false
+ authme.player.seeotheraccounts:
+ description: Permission for user to see other accounts.
+ default: false
diff --git a/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java b/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java
index 9acc3c25e..ef78c5fda 100644
--- a/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java
+++ b/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java
@@ -142,30 +142,44 @@ public abstract class AbstractEncryptionMethodTest {
return method.comparePassword(password, hashes.get(password), USERNAME);
}
- // @org.junit.Test public void a() { AbstractEncryptionMethodTest.generateTest(); }
- // TODO #364: Remove this method
+ /**
+ * Generates a test class for a given encryption method. Simply create a test class and run the following code,
+ * replacing {@code XXX} with the actual class:
+ *
+ * The output is the entire test class.
+ *
+ * @param method The method to create a test class for
+ */
static void generateTest(EncryptionMethod method) {
String className = method.getClass().getSimpleName();
+ // Create javadoc and "public class extends" and the constructor call "super(new Class(),"
System.out.println("/**\n * Test for {@link " + className + "}.\n */");
System.out.println("public class " + className + "Test extends AbstractEncryptionMethodTest {");
System.out.println("\n\tpublic " + className + "Test() {");
System.out.println("\t\tsuper(new " + className + "(),");
+ // Iterate through the GIVEN_PASSWORDS and generate a hash so we can always check it later
String delim = ", ";
for (String password : GIVEN_PASSWORDS) {
if (password.equals(GIVEN_PASSWORDS[GIVEN_PASSWORDS.length - 1])) {
delim = "); ";
}
+ // Encr. method uses separate salt, so we need to call the constructor that takes HashedPassword instances
if (method.hasSeparateSalt()) {
HashedPassword hashedPassword = method.computeHash(password, USERNAME);
System.out.println(String.format("\t\tnew HashedPassword(\"%s\", \"%s\")%s// %s",
hashedPassword.getHash(), hashedPassword.getSalt(), delim, password));
} else {
+ // Encryption method doesn't have separate salt, so simply pass the generated hash to the constructor
System.out.println("\t\t\"" + method.computeHash(password, USERNAME).getHash()
+ "\"" + delim + "// " + password);
}
}
+
+ // Close the constructor and class declarations
System.out.println("\t}");
System.out.println("\n}");
}
diff --git a/src/tools/docs/hash_algorithms.md b/src/tools/docs/hash_algorithms.md
new file mode 100644
index 000000000..60a011b4c
--- /dev/null
+++ b/src/tools/docs/hash_algorithms.md
@@ -0,0 +1,78 @@
+
+
+
+## Hash Algorithms
+AuthMe supports the following hash algorithms for storing your passwords safely.
+
+
+Algorithm | Recommendation | Hash length | ASCII | | Salt type | Length | Separate?
+--------- | -------------- | ----------- | ----- | --- | --------- | ------ | ---------
+BCRYPT | Recommended | 60 | | | Text | |
+BCRYPT2Y | Recommended | 60 | | | Text | 22 |
+CRAZYCRYPT1 | Do not use | 128 | | | Username | |
+DOUBLEMD5 | Do not use | 32 | | | None | |
+IPB3 | Acceptable | 32 | | | Text | 5 | Y
+JOOMLA | Recommended | 65 | | | Text | 32 |
+MD5 | Do not use | 32 | | | None | |
+MD5VB | Acceptable | 56 | | | Text | 16 |
+MYBB | Acceptable | 32 | | | Text | 8 | Y
+PBKDF2 | Does not work | 330 | | | Text | 12 |
+PBKDF2DJANGO | Acceptable | 77 | Y | | Text | 12 |
+PHPBB | Acceptable | 34 | | | Text | 16 |
+PHPFUSION | Do not use | 64 | Y | | | | Y
+ROYALAUTH | Do not use | 128 | | | None | |
+SALTED2MD5 | Acceptable | 32 | | | Text | | Y
+SALTEDSHA512 | Recommended | 128 | | | | | Y
+SHA1 | Do not use | 40 | | | None | |
+SHA256 | Recommended | 86 | | | Text | 16 |
+SHA512 | Do not use | 128 | | | None | |
+SMF | Do not use | 40 | | | Username | |
+WBB3 | Acceptable | 40 | | | Text | 40 | Y
+WBB4 | Does not work | 60 | | | Text | 8 |
+WHIRLPOOL | Do not use | 128 | | | None | |
+WORDPRESS | Do not use | 34 | | | Text | 9 |
+XAUTH | Recommended | 140 | | | Text | 12 |
+CUSTOM | | | | | | | |
+
+
+
+### Columns
+#### Algorithm
+The algorithm is the hashing algorithm used to store passwords with. Default is SHA256 and is recommended.
+You can change the hashing algorithm in the config.yml: under `security`, locate `passwordHash`.
+
+#### Recommendation
+The recommendation lists our usage recommendation in terms of how secure it is (not how _well_ the algorithm works!).
+- Recommended: The hash algorithm appears to be cryptographically secure and is one we recommend.
+- Acceptable: There are safer algorithms that can be chosen but using the algorithm is generally OK.
+- Do not use: Hash algorithm isn't sufficiently secure. Use only if required to hook into another system.
+- Does not work: The algorithm does not work properly; do not use.
+
+#### Hash Length
+The length of the hashes the algorithm produces. Note that the hash length is not (primarily) indicative of
+whether an algorithm is secure or not.
+
+#### ASCII
+If denoted with a **y**, means that the algorithm is restricted to ASCII characters only, i.e. it will simply ignore
+"special characters" such as `ÿ` or `Â`. Note that we do not recommend the use of "special characters" in passwords.
+
+#### Salt Columns
+Before hashing, a _salt_ may be appended to the password to make the hash more secure. The following columns describe
+the salt the algorithm uses.
+
+
+##### Salt Type
+We do not recommend the usage
+of any algorithm that doesn't use a randomly generated text as salt. This "salt type" column indicates what type of
+salt the algorithm uses:
+- Text: randomly generated text (see also the following column, "Length")
+- Username: the salt is constructed from the username (bad)
+- None: the algorithm uses no salt (bad)
+
+##### Length
+If applicable (salt type is "Text"), indicates the length of the generated salt. The longer the better.
+If this column is empty when the salt type is "Text", it typically means the salt length can be defined in config.yml.
+
+##### Separate
+If denoted with a **y**, it means that the salt is stored in a separate column in the database. This is neither good
+or bad.
diff --git a/src/tools/hashmethods/EncryptionMethodInfoGatherer.java b/src/tools/hashmethods/EncryptionMethodInfoGatherer.java
new file mode 100644
index 000000000..07c588ea5
--- /dev/null
+++ b/src/tools/hashmethods/EncryptionMethodInfoGatherer.java
@@ -0,0 +1,135 @@
+package hashmethods;
+
+import fr.xephi.authme.security.HashAlgorithm;
+import fr.xephi.authme.security.crypts.EncryptionMethod;
+import fr.xephi.authme.security.crypts.HexSaltedMethod;
+import fr.xephi.authme.security.crypts.description.AsciiRestricted;
+import fr.xephi.authme.security.crypts.description.HasSalt;
+import fr.xephi.authme.security.crypts.description.Recommendation;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.collect.Sets.newHashSet;
+
+/**
+ * Gathers information on {@link fr.xephi.authme.security.crypts.EncryptionMethod} implementations based on
+ * the annotations in {@link fr.xephi.authme.security.crypts.description}.
+ */
+public class EncryptionMethodInfoGatherer {
+
+ @SuppressWarnings("unchecked")
+ private final static Set> RELEVANT_ANNOTATIONS =
+ newHashSet(HasSalt.class, Recommendation.class, AsciiRestricted.class);
+
+ private Map descriptions;
+
+ public EncryptionMethodInfoGatherer() {
+ descriptions = new LinkedHashMap<>();
+ constructDescriptions();
+ }
+
+ public Map getDescriptions() {
+ return descriptions;
+ }
+
+ private void constructDescriptions() {
+ for (HashAlgorithm algorithm : HashAlgorithm.values()) {
+ Class extends EncryptionMethod> methodClazz = algorithm.getClazz();
+ if (!HashAlgorithm.CUSTOM.equals(algorithm) && !methodClazz.isAnnotationPresent(Deprecated.class)) {
+ MethodDescription description = createDescription(methodClazz);
+ descriptions.put(algorithm, description);
+ }
+ }
+ }
+
+ private static MethodDescription createDescription(Class extends EncryptionMethod> clazz) {
+ EncryptionMethod method = instantiateMethod(clazz);
+ MethodDescription description = new MethodDescription(clazz);
+ description.setHashLength(method.computeHash("test", "user").getHash().length());
+ description.setHasSeparateSalt(method.hasSeparateSalt());
+
+ Map, Annotation> annotationMap = gatherAnnotations(clazz);
+ if (annotationMap.containsKey(HasSalt.class)) {
+ setSaltInformation(description, returnTyped(annotationMap, HasSalt.class), method);
+ }
+ if (annotationMap.containsKey(Recommendation.class)) {
+ description.setUsage(returnTyped(annotationMap, Recommendation.class).value());
+ }
+ if (annotationMap.containsKey(AsciiRestricted.class)) {
+ description.setAsciiRestricted(true);
+ }
+ return description;
+ }
+
+ private static Map, Annotation> gatherAnnotations(Class> methodClass) {
+ // Note ljacqu 20151231: The map could be Map, Annotation> and it has the constraint
+ // that for a key Class, the value is of type T. We write a simple "Class>" for brevity.
+ Map, Annotation> collection = new HashMap<>();
+ Class> currentMethodClass = methodClass;
+ while (currentMethodClass != null) {
+ getRelevantAnnotations(currentMethodClass, collection);
+ currentMethodClass = getSuperClass(currentMethodClass);
+ }
+ return collection;
+ }
+
+ // Parameters could be Class extends EncryptionMethod>; Map, Annotation>
+ // but the constraint doesn't have any technical relevance, so just clutters the code
+ private static void getRelevantAnnotations(Class> methodClass, Map, Annotation> collection) {
+ for (Annotation annotation : methodClass.getAnnotations()) {
+ if (RELEVANT_ANNOTATIONS.contains(annotation.annotationType())
+ && !collection.containsKey(annotation.annotationType())) {
+ collection.put(annotation.annotationType(), annotation);
+ }
+ }
+ }
+
+ /**
+ * Returns the super class of the given encryption method if it is also of EncryptionMethod type.
+ * (Anything beyond EncryptionMethod is not of interest.)
+ */
+ private static Class> getSuperClass(Class> methodClass) {
+ Class> zuper = methodClass.getSuperclass();
+ if (EncryptionMethod.class.isAssignableFrom(zuper)) {
+ return zuper;
+ }
+ return null;
+ }
+
+ /**
+ * Set the salt information for the given encryption method and the found {@link HasSalt} annotation.
+ * Also gets the salt length from {@link HexSaltedMethod#getSaltLength()} for such instances.
+ *
+ * @param description The description to update
+ * @param hasSalt The associated HasSalt annotation
+ * @param method The encryption method
+ */
+ private static void setSaltInformation(MethodDescription description, HasSalt hasSalt, EncryptionMethod method) {
+ description.setSaltType(hasSalt.value());
+ if (hasSalt.length() != 0) {
+ description.setSaltLength(hasSalt.length());
+ } else if (method instanceof HexSaltedMethod) {
+ int saltLength = ((HexSaltedMethod) method).getSaltLength();
+ description.setSaltLength(saltLength);
+ }
+ }
+
+ private static EncryptionMethod instantiateMethod(Class extends EncryptionMethod> clazz) {
+ try {
+ return clazz.newInstance();
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new RuntimeException("Could not instantiate " + clazz, e);
+ }
+ }
+
+ // Convenience method for retrieving an annotation in a typed fashion.
+ // We know implicitly that the key of the map always corresponds to the type of the value
+ private static T returnTyped(Map, Annotation> map, Class key) {
+ return key.cast(map.get(key));
+ }
+
+}
diff --git a/src/tools/hashmethods/HashAlgorithmsDescriptionTask.java b/src/tools/hashmethods/HashAlgorithmsDescriptionTask.java
new file mode 100644
index 000000000..5213d6b7d
--- /dev/null
+++ b/src/tools/hashmethods/HashAlgorithmsDescriptionTask.java
@@ -0,0 +1,100 @@
+package hashmethods;
+
+import fr.xephi.authme.security.HashAlgorithm;
+import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.util.WrapperMock;
+import utils.ANewMap;
+import utils.FileUtils;
+import utils.TagReplacer;
+import utils.ToolTask;
+import utils.ToolsConstants;
+
+import java.util.Map;
+import java.util.Scanner;
+
+/**
+ * Task for generating the markdown page describing the AuthMe hash algorithms.
+ *
+ * @see {@link fr.xephi.authme.security.HashAlgorithm}
+ */
+public class HashAlgorithmsDescriptionTask implements ToolTask {
+
+ private static final String CUR_FOLDER = ToolsConstants.TOOLS_SOURCE_ROOT + "hashmethods/";
+ private static final String OUTPUT_FILE = ToolsConstants.DOCS_FOLDER + "hash_algorithms.md";
+
+ @Override
+ public void execute(Scanner scanner) {
+ // Unfortunately, we need the Wrapper to be around to work with Settings, and certain encryption methods
+ // directly read from the Settings file
+ WrapperMock.createInstance();
+ Settings.bCryptLog2Rounds = 8;
+ Settings.saltLength = 8;
+
+ // Gather info and construct a row for each method
+ EncryptionMethodInfoGatherer infoGatherer = new EncryptionMethodInfoGatherer();
+ Map descriptions = infoGatherer.getDescriptions();
+ final String methodRows = constructMethodRows(descriptions);
+
+ // Write to the docs file
+ Map tags = ANewMap.with("method_rows", methodRows).build();
+ FileUtils.generateFileFromTemplate(CUR_FOLDER + "hash_algorithms.tpl.md", OUTPUT_FILE, tags);
+ }
+
+ private static String constructMethodRows(Map descriptions) {
+ final String rowTemplate = FileUtils.readFromFile(CUR_FOLDER + "hash_algorithms_row.tpl.md");
+ StringBuilder result = new StringBuilder();
+ for (Map.Entry entry : descriptions.entrySet()) {
+ MethodDescription description = entry.getValue();
+ Map tags = ANewMap
+ .with("name", asString(entry.getKey()))
+ .and("recommendation", asString(description.getUsage()))
+ .and("hash_length", asString(description.getHashLength()))
+ .and("ascii_restricted", asString(description.isAsciiRestricted()))
+ .and("salt_type", asString(description.getSaltType()))
+ .and("salt_length", asString(description.getSaltLength()))
+ .and("separate_salt", asString(description.hasSeparateSalt()))
+ .build();
+ result.append(TagReplacer.applyReplacements(rowTemplate, tags));
+ }
+ return result.toString();
+ }
+
+ @Override
+ public String getTaskName() {
+ return "describeHashAlgos";
+ }
+
+ // ----
+ // String representations
+ // ----
+ private static String asString(boolean value) {
+ return value ? "Y" : "";
+ }
+
+ private static String asString(int value) {
+ return String.valueOf(value);
+ }
+
+ private static String asString(Integer value) {
+ if (value == null) {
+ return "";
+ }
+ return String.valueOf(value);
+ }
+
+ private static String asString(HashAlgorithm value) {
+ return value.toString();
+ }
+
+ private static > String asString(E value) {
+ if (value == null) {
+ return "";
+ }
+ // Get the enum name and replace something like "DO_NOT_USE" to "Do not use"
+ String enumName = value.toString().replace("_", " ");
+ return enumName.length() > 2
+ ? enumName.substring(0, 1) + enumName.substring(1).toLowerCase()
+ : enumName;
+ }
+
+}
diff --git a/src/tools/hashmethods/MethodDescription.java b/src/tools/hashmethods/MethodDescription.java
new file mode 100644
index 000000000..45aaf448e
--- /dev/null
+++ b/src/tools/hashmethods/MethodDescription.java
@@ -0,0 +1,85 @@
+package hashmethods;
+
+import fr.xephi.authme.security.crypts.EncryptionMethod;
+import fr.xephi.authme.security.crypts.description.SaltType;
+import fr.xephi.authme.security.crypts.description.Usage;
+
+/**
+ * Description of a {@link EncryptionMethod}.
+ */
+public class MethodDescription {
+
+ /** The implementation class the description belongs to. */
+ private final Class extends EncryptionMethod> method;
+ /** The type of the salt that is used. */
+ private SaltType saltType;
+ /** The length of the salt for SaltType.TEXT salts. */
+ private Integer saltLength;
+ /** The usage recommendation. */
+ private Usage usage;
+ /** Whether or not the encryption method is restricted to ASCII characters for proper functioning. */
+ private boolean asciiRestricted;
+ /** Whether or not the encryption method requires its salt stored separately. */
+ private boolean hasSeparateSalt;
+ /** The length of the hash output, based on a test hash (i.e. assumes same length for all hashes.) */
+ private int hashLength;
+
+ public MethodDescription(Class extends EncryptionMethod> method) {
+ this.method = method;
+ }
+
+
+ // Trivial getters and setters
+ public Class extends EncryptionMethod> getMethod() {
+ return method;
+ }
+
+ public SaltType getSaltType() {
+ return saltType;
+ }
+
+ public void setSaltType(SaltType saltType) {
+ this.saltType = saltType;
+ }
+
+ public Integer getSaltLength() {
+ return saltLength;
+ }
+
+ public void setSaltLength(int saltLength) {
+ this.saltLength = saltLength;
+ }
+
+ public Usage getUsage() {
+ return usage;
+ }
+
+ public void setUsage(Usage usage) {
+ this.usage = usage;
+ }
+
+ public boolean isAsciiRestricted() {
+ return asciiRestricted;
+ }
+
+ public void setAsciiRestricted(boolean asciiRestricted) {
+ this.asciiRestricted = asciiRestricted;
+ }
+
+ public boolean hasSeparateSalt() {
+ return hasSeparateSalt;
+ }
+
+ public void setHasSeparateSalt(boolean hasSeparateSalt) {
+ this.hasSeparateSalt = hasSeparateSalt;
+ }
+
+ public int getHashLength() {
+ return hashLength;
+ }
+
+ public void setHashLength(int hashLength) {
+ this.hashLength = hashLength;
+ }
+
+}
diff --git a/src/tools/hashmethods/hash_algorithms.tpl.md b/src/tools/hashmethods/hash_algorithms.tpl.md
new file mode 100644
index 000000000..b466eeebd
--- /dev/null
+++ b/src/tools/hashmethods/hash_algorithms.tpl.md
@@ -0,0 +1,53 @@
+
+
+
+## Hash Algorithms
+AuthMe supports the following hash algorithms for storing your passwords safely.
+
+
+Algorithm | Recommendation | Hash length | ASCII | | Salt type | Length | Separate?
+--------- | -------------- | ----------- | ----- | --- | --------- | ------ | ---------
+{method_rows}CUSTOM | | | | | | | |
+
+
+
+### Columns
+#### Algorithm
+The algorithm is the hashing algorithm used to store passwords with. Default is SHA256 and is recommended.
+You can change the hashing algorithm in the config.yml: under `security`, locate `passwordHash`.
+
+#### Recommendation
+The recommendation lists our usage recommendation in terms of how secure it is (not how _well_ the algorithm works!).
+- Recommended: The hash algorithm appears to be cryptographically secure and is one we recommend.
+- Acceptable: There are safer algorithms that can be chosen but using the algorithm is generally OK.
+- Do not use: Hash algorithm isn't sufficiently secure. Use only if required to hook into another system.
+- Does not work: The algorithm does not work properly; do not use.
+
+#### Hash Length
+The length of the hashes the algorithm produces. Note that the hash length is not (primarily) indicative of
+whether an algorithm is secure or not.
+
+#### ASCII
+If denoted with a **y**, means that the algorithm is restricted to ASCII characters only, i.e. it will simply ignore
+"special characters" such as `ÿ` or `Â`. Note that we do not recommend the use of "special characters" in passwords.
+
+#### Salt Columns
+Before hashing, a _salt_ may be appended to the password to make the hash more secure. The following columns describe
+the salt the algorithm uses.
+
+
+##### Salt Type
+We do not recommend the usage
+of any algorithm that doesn't use a randomly generated text as salt. This "salt type" column indicates what type of
+salt the algorithm uses:
+- Text: randomly generated text (see also the following column, "Length")
+- Username: the salt is constructed from the username (bad)
+- None: the algorithm uses no salt (bad)
+
+##### Length
+If applicable (salt type is "Text"), indicates the length of the generated salt. The longer the better.
+If this column is empty when the salt type is "Text", it typically means the salt length can be defined in config.yml.
+
+##### Separate
+If denoted with a **y**, it means that the salt is stored in a separate column in the database. This is neither good
+or bad.
diff --git a/src/tools/hashmethods/hash_algorithms_row.tpl.md b/src/tools/hashmethods/hash_algorithms_row.tpl.md
new file mode 100644
index 000000000..411d11271
--- /dev/null
+++ b/src/tools/hashmethods/hash_algorithms_row.tpl.md
@@ -0,0 +1 @@
+{name} | {recommendation} | {hash_length} | {ascii_restricted} | | {salt_type} | {salt_length} | {separate_salt}