Merge pull request #631 from AuthMe-Team/master

Sync with dev repo
This commit is contained in:
Gabriele C 2016-04-01 07:56:51 +02:00
commit 4d967563dd
164 changed files with 5937 additions and 3100 deletions

View File

@ -4,7 +4,7 @@
#####News: #####News:
- We are going to release a stable (and working!) version of AuthMeBungee, in the meantime, a fixed version of the unofficial AuthMeBridgeBukkit plugin can be found at: https://github.com/Xephi/AuthMeReloaded/issues/557 Thanks to @beetle2k - Latest version of AuthMeBridge is finally compatible with latest AuthMe snapshots! ;)
#####Development tools: #####Development tools:
@ -62,7 +62,7 @@ McStats: http://mcstats.org/plugin/AuthMe
#####"The best authentication plugin for the Bukkit/Spigot API!" #####"The best authentication plugin for the Bukkit/Spigot API!"
<p>Prevent username stealing on your server! Fully compatible with UUIDs and Craftbukkit/Spigot 1.8.X!<br> <p>Prevent username stealing on your server!<br>
Use it to secure your Offline mode server or to increase your Online mode server's protection!</p> Use it to secure your Offline mode server or to increase your Online mode server's protection!</p>
<p>AuthMeReloaded disallows players who aren't authenticated to do actions like placing blocks, moving,<br> <p>AuthMeReloaded disallows players who aren't authenticated to do actions like placing blocks, moving,<br>

143
pom.xml
View File

@ -48,22 +48,25 @@
</prerequisites> </prerequisites>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Project Properties --> <!-- Project Properties -->
<projectEncoding>UTF-8</projectEncoding>
<project.build.sourceEncoding>${projectEncoding}</project.build.sourceEncoding>
<project.build.outputEncoding>${projectEncoding}</project.build.outputEncoding>
<jdkVersion>1.7</jdkVersion>
<testJreVersion>1.7</testJreVersion>
<!-- Output properties -->
<pluginName>AuthMe</pluginName> <pluginName>AuthMe</pluginName>
<jarName>${pluginName}-${project.version}</jarName> <jarName>${pluginName}-${project.version}</jarName>
<mainClass>fr.xephi.authme.AuthMe</mainClass> <mainClass>${project.groupId}.${project.artifactId}.${pluginName}</mainClass>
<pluginAuthors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu</pluginAuthors> <pluginAuthors>Xephi, sgdc3, DNx5, timvisee, games647, ljacqu</pluginAuthors>
<buildNumber>Unknown</buildNumber> <buildNumber>Unknown</buildNumber>
<!-- Change Compiler Version (JDK) HERE! -->
<javaVersion>1.7</javaVersion>
<!-- Change Bukkit Version HERE! --> <!-- Change Bukkit Version HERE! -->
<bukkitVersion>1.9-pre1-SNAPSHOT</bukkitVersion> <bukkitVersion>1.9-R0.1-SNAPSHOT</bukkitVersion>
</properties> </properties>
<!-- Jenkins profile (add the real buildNumber to the version string) -->
<profiles> <profiles>
<profile> <profile>
<id>jenkins</id> <id>jenkins</id>
@ -84,33 +87,21 @@
<testSourceDirectory>src/test/java</testSourceDirectory> <testSourceDirectory>src/test/java</testSourceDirectory>
<resources> <resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>plugin.yml</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory>
<includes>
<include>email.html</include>
<include>welcome.txt</include>
</includes>
</resource>
<resource> <resource>
<targetPath>.</targetPath> <targetPath>.</targetPath>
<filtering>false</filtering> <filtering>false</filtering>
<directory>.</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources/</directory> <directory>src/main/resources/</directory>
<includes> <includes>
<include>*.yml</include> <include>*</include>
</includes> </includes>
<excludes>
<exclude>plugin.yml</exclude>
</excludes>
</resource> </resource>
<resource> <resource>
<targetPath>./messages/</targetPath> <targetPath>./messages/</targetPath>
@ -128,15 +119,28 @@
</testResources> </testResources>
<plugins> <plugins>
<!-- Maven Java Compiler -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version> <version>3.5.1</version>
<configuration> <configuration>
<source>1.7</source> <source>${jdkVersion}</source>
<target>${javaVersion}</target> <target>${jdkVersion}</target>
<testSource>${testJreVersion}</testSource>
<testTarget>${testJreVersion}</testTarget>
</configuration> </configuration>
</plugin> </plugin>
<!-- Test Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Dfile.encoding=${projectEncoding} ${argLine}</argLine>
</configuration>
</plugin>
<!-- Libs Shading and Relocation -->
<plugin> <plugin>
<!--Relocate all lib we use in order to fix class loading errors if we use different versions <!--Relocate all lib we use in order to fix class loading errors if we use different versions
than already loaded libs (i.e. by Mojang -> gson)--> than already loaded libs (i.e. by Mojang -> gson)-->
@ -161,33 +165,11 @@
</excludes> </excludes>
</artifactSet> </artifactSet>
<relocations> <relocations>
<!--We use a newer version of gson so include it to the jar and reference to the new version--> <!-- We use a newer version of gson so we need to include it! -->
<relocation> <relocation>
<pattern>com.google.gson</pattern> <pattern>com.google.gson</pattern>
<shadedPattern>fr.xephi.authme.libs.google</shadedPattern> <shadedPattern>fr.xephi.authme.libs.google</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
<!--
<relocation>
<pattern>org.apache</pattern>
<shadedPattern>fr.xephi.authme.libs.apache</shadedPattern>
</relocation>
<relocation>
<pattern>javax.mail</pattern>
<shadedPattern>fr.xephi.authme.libs.javax.mail</shadedPattern>
</relocation>
<relocation>
<pattern>javax.activation</pattern>
<shadedPattern>fr.xephi.authme.libs.javax.activation</shadedPattern>
</relocation>
<relocation>
<pattern>com.sun</pattern>
<shadedPattern>fr.xephi.authme.libs.sun</shadedPattern>
</relocation>
-->
<relocation> <relocation>
<pattern>com.zaxxer.hikari</pattern> <pattern>com.zaxxer.hikari</pattern>
<shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern> <shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern>
@ -204,6 +186,11 @@
<pattern>net.ricecode.similarity</pattern> <pattern>net.ricecode.similarity</pattern>
<shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern> <shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern>
</relocation> </relocation>
<!-- MCStats.org metrics -->
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
</relocations> </relocations>
<outputFile>target/${jarName}-spigot.jar</outputFile> <outputFile>target/${jarName}-spigot.jar</outputFile>
</configuration> </configuration>
@ -215,34 +202,12 @@
<goal>shade</goal> <goal>shade</goal>
</goals> </goals>
<configuration> <configuration>
<!--Include all google libraries, because they are not avaialbe before 1.8--> <!-- Include all google libraries, because they are not available before 1.8 -->
<relocations> <relocations>
<relocation> <relocation>
<pattern>com.google</pattern> <pattern>com.google</pattern>
<shadedPattern>fr.xephi.authme.libs.google</shadedPattern> <shadedPattern>fr.xephi.authme.libs.google</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
<!--
<relocation>
<pattern>org.apache</pattern>
<shadedPattern>fr.xephi.authme.libs.apache</shadedPattern>
</relocation>
<relocation>
<pattern>javax.mail</pattern>
<shadedPattern>fr.xephi.authme.libs.javax.mail</shadedPattern>
</relocation>
<relocation>
<pattern>javax.activation</pattern>
<shadedPattern>fr.xephi.authme.libs.javax.activation</shadedPattern>
</relocation>
<relocation>
<pattern>com.sun</pattern>
<shadedPattern>fr.xephi.authme.libs.sun</shadedPattern>
</relocation>
-->
<relocation> <relocation>
<pattern>com.zaxxer.hikari</pattern> <pattern>com.zaxxer.hikari</pattern>
<shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern> <shadedPattern>fr.xephi.authme.libs.hikari</shadedPattern>
@ -259,16 +224,22 @@
<pattern>net.ricecode.similarity</pattern> <pattern>net.ricecode.similarity</pattern>
<shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern> <shadedPattern>fr.xephi.authme.libs.similarity</shadedPattern>
</relocation> </relocation>
<!-- MCStats.org metrics -->
<relocation>
<pattern>org.mcstats</pattern>
<shadedPattern>fr.xephi.authme</shadedPattern>
</relocation>
</relocations> </relocations>
<outputFile>target/${jarName}-legacy.jar</outputFile> <outputFile>target/${jarName}-legacy.jar</outputFile>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- Test coverage -->
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version> <version>0.7.6.201602180812</version>
<executions> <executions>
<execution> <execution>
<id>prepare-agent</id> <id>prepare-agent</id>
@ -278,11 +249,15 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- Coveralls data -->
<plugin> <plugin>
<groupId>org.eluder.coveralls</groupId> <groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId> <artifactId>coveralls-maven-plugin</artifactId>
<version>4.1.0</version> <version>4.1.0</version>
<!-- Token is provided by mvn command --> <configuration>
<failOnServiceError>false</failOnServiceError>
</configuration>
<!-- The secret token is provided by console! -->
</plugin> </plugin>
<!-- Javadocs settings --> <!-- Javadocs settings -->
<plugin> <plugin>
@ -293,6 +268,8 @@
<charset>UTF-8</charset> <charset>UTF-8</charset>
<docencoding>UTF-8</docencoding> <docencoding>UTF-8</docencoding>
<docfilessubdirs>true</docfilessubdirs> <docfilessubdirs>true</docfilessubdirs>
<show>public</show>
<failOnError>false</failOnError>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
@ -359,7 +336,7 @@
<dependency> <dependency>
<groupId>com.zaxxer</groupId> <groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId> <artifactId>HikariCP</artifactId>
<version>2.4.3</version> <version>2.4.5</version>
<scope>compile</scope> <scope>compile</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>
@ -371,8 +348,8 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId> <artifactId>slf4j-simple</artifactId>
<version>1.7.16</version> <version>1.7.20</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@ -413,7 +390,7 @@
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.6.1</version> <version>2.6.2</version>
<scope>compile</scope> <scope>compile</scope>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
@ -687,7 +664,7 @@
<dependency> <dependency>
<groupId>net.minelink</groupId> <groupId>net.minelink</groupId>
<artifactId>CombatTagPlus</artifactId> <artifactId>CombatTagPlus</artifactId>
<version>1.2.1-SNAPSHOT</version> <version>1.2.2-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
<exclusions> <exclusions>
<exclusion> <exclusion>

View File

@ -2,92 +2,106 @@ package fr.xephi.authme;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.util.Wrapper; import fr.xephi.authme.settings.properties.ProtectionSettings;
import org.bukkit.Bukkit; import fr.xephi.authme.util.BukkitService;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_MINUTE;
import static fr.xephi.authme.util.BukkitService.TICKS_PER_SECOND;
/** /**
* The AntiBot Service Management class. * The AntiBot Service Management class.
*/ */
public class AntiBot { public class AntiBot {
private static final Wrapper wrapper = Wrapper.getInstance(); private final NewSetting settings;
private static final AuthMe plugin = wrapper.getAuthMe(); private final Messages messages;
private static final Messages messages = wrapper.getMessages(); private final PermissionsManager permissionsManager;
private static final List<String> antibotPlayers = new ArrayList<>(); private final BukkitService bukkitService;
private static AntiBotStatus antiBotStatus = AntiBotStatus.DISABLED; private final List<String> antibotPlayers = new ArrayList<>();
private AntiBotStatus antiBotStatus = AntiBotStatus.DISABLED;
public static void setupAntiBotService() { public AntiBot(NewSetting settings, Messages messages, PermissionsManager permissionsManager,
if (!Settings.enableAntiBot) { BukkitService bukkitService) {
return; this.settings = settings;
this.messages = messages;
this.permissionsManager = permissionsManager;
this.bukkitService = bukkitService;
setupAntiBotService();
}
private void setupAntiBotService() {
if (settings.getProperty(ProtectionSettings.ENABLE_ANTIBOT)) {
bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override
public void run() {
antiBotStatus = AntiBotStatus.LISTENING;
}
}, 2 * TICKS_PER_MINUTE);
} }
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { }
@Override
public void run() { public void overrideAntiBotStatus(boolean activated) {
if (antiBotStatus != AntiBotStatus.DISABLED) {
if (activated) {
antiBotStatus = AntiBotStatus.ACTIVE;
} else {
antiBotStatus = AntiBotStatus.LISTENING; antiBotStatus = AntiBotStatus.LISTENING;
} }
}, 2400);
}
public static void overrideAntiBotStatus(boolean activated) {
if (antiBotStatus == AntiBotStatus.DISABLED) {
return;
}
if (activated) {
antiBotStatus = AntiBotStatus.ACTIVE;
} else {
antiBotStatus = AntiBotStatus.LISTENING;
} }
} }
public static AntiBotStatus getAntiBotStatus() { public AntiBotStatus getAntiBotStatus() {
return antiBotStatus; return antiBotStatus;
} }
public static void activateAntiBot() { public void activateAntiBot() {
antiBotStatus = AntiBotStatus.ACTIVE; antiBotStatus = AntiBotStatus.ACTIVE;
for (String s : messages.retrieve(MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE)) { for (String s : messages.retrieve(MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE)) {
Bukkit.broadcastMessage(s); bukkitService.broadcastMessage(s);
} }
wrapper.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { final int duration = settings.getProperty(ProtectionSettings.ANTIBOT_DURATION);
bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
if (antiBotStatus == AntiBotStatus.ACTIVE) { if (antiBotStatus == AntiBotStatus.ACTIVE) {
antiBotStatus = AntiBotStatus.LISTENING; antiBotStatus = AntiBotStatus.LISTENING;
antibotPlayers.clear(); antibotPlayers.clear();
for (String s : messages.retrieve(MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE)) { for (String s : messages.retrieve(MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE)) {
Bukkit.broadcastMessage(s.replace("%m", "" + Settings.antiBotDuration)); bukkitService.broadcastMessage(s.replace("%m", Integer.toString(duration)));
} }
} }
} }
}, Settings.antiBotDuration * 1200); }, duration * TICKS_PER_MINUTE);
} }
public static void checkAntiBot(final Player player) { public void checkAntiBot(final Player player) {
if (antiBotStatus == AntiBotStatus.ACTIVE || antiBotStatus == AntiBotStatus.DISABLED) { if (antiBotStatus == AntiBotStatus.ACTIVE || antiBotStatus == AntiBotStatus.DISABLED) {
return; return;
} }
if (plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) { if (permissionsManager.hasPermission(player, PlayerStatePermission.BYPASS_ANTIBOT)) {
return; return;
} }
antibotPlayers.add(player.getName().toLowerCase()); antibotPlayers.add(player.getName().toLowerCase());
if (antibotPlayers.size() > Settings.antiBotSensibility) { if (antibotPlayers.size() > settings.getProperty(ProtectionSettings.ANTIBOT_SENSIBILITY)) {
activateAntiBot(); activateAntiBot();
return; return;
} }
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { bukkitService.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
antibotPlayers.remove(player.getName().toLowerCase()); antibotPlayers.remove(player.getName().toLowerCase());
} }
}, 300); }, 15 * TICKS_PER_SECOND);
} }
public enum AntiBotStatus { public enum AntiBotStatus {

View File

@ -1,11 +1,8 @@
package fr.xephi.authme; 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.API;
import fr.xephi.authme.api.NewAPI; import fr.xephi.authme.api.NewAPI;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.backup.JsonCache; import fr.xephi.authme.cache.backup.JsonCache;
@ -24,7 +21,7 @@ import fr.xephi.authme.datasource.FlatFile;
import fr.xephi.authme.datasource.MySQL; import fr.xephi.authme.datasource.MySQL;
import fr.xephi.authme.datasource.SQLite; import fr.xephi.authme.datasource.SQLite;
import fr.xephi.authme.hooks.BungeeCordMessage; import fr.xephi.authme.hooks.BungeeCordMessage;
import fr.xephi.authme.hooks.EssSpawn; import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.listener.AuthMeBlockListener; import fr.xephi.authme.listener.AuthMeBlockListener;
import fr.xephi.authme.listener.AuthMeEntityListener; import fr.xephi.authme.listener.AuthMeEntityListener;
import fr.xephi.authme.listener.AuthMeInventoryPacketAdapter; import fr.xephi.authme.listener.AuthMeInventoryPacketAdapter;
@ -42,24 +39,29 @@ import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Management; import fr.xephi.authme.process.Management;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.SHA256; import fr.xephi.authme.security.crypts.SHA256;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.OtherAccounts;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SettingsMigrationService; import fr.xephi.authme.settings.SettingsMigrationService;
import fr.xephi.authme.settings.Spawn; import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.properties.DatabaseSettings; import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.settings.properties.EmailSettings;
import fr.xephi.authme.settings.properties.HooksSettings; import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.PurgeSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings; import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.settings.properties.SettingsFieldRetriever;
import fr.xephi.authme.settings.propertymap.PropertyMap;
import fr.xephi.authme.util.BukkitService;
import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.FileUtils;
import fr.xephi.authme.util.GeoLiteAPI; import fr.xephi.authme.util.GeoLiteAPI;
import fr.xephi.authme.util.MigrationService; import fr.xephi.authme.util.MigrationService;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import net.minelink.ctplus.CombatTagPlus;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -72,8 +74,6 @@ import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
@ -111,7 +111,7 @@ public class AuthMe extends JavaPlugin {
public final ConcurrentHashMap<String, BukkitTask> sessions = new ConcurrentHashMap<>(); public final ConcurrentHashMap<String, BukkitTask> sessions = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, Integer> captcha = new ConcurrentHashMap<>(); public final ConcurrentHashMap<String, Integer> captcha = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, String> cap = new ConcurrentHashMap<>(); public final ConcurrentHashMap<String, String> cap = new ConcurrentHashMap<>();
public final ConcurrentHashMap<String, String> realIp = new ConcurrentHashMap<>();
/* /*
* Public Instances * Public Instances
* TODO #432: Encapsulation * TODO #432: Encapsulation
@ -119,26 +119,26 @@ public class AuthMe extends JavaPlugin {
public NewAPI api; public NewAPI api;
public SendMailSSL mail; public SendMailSSL mail;
public DataManager dataManager; public DataManager dataManager;
public OtherAccounts otherAccounts;
public Location essentialsSpawn;
/* /*
* Plugin Hooks * Plugin Hooks
* TODO: Move into modules * TODO: Move into modules
*/ */
public Essentials ess;
public MultiverseCore multiverse;
public CombatTagPlus combatTagPlus;
public AuthMeInventoryPacketAdapter inventoryProtector; public AuthMeInventoryPacketAdapter inventoryProtector;
public AuthMeTabCompletePacketAdapter tabComplete; public AuthMeTabCompletePacketAdapter tabComplete;
public AuthMeTablistPacketAdapter tablistHider; public AuthMeTablistPacketAdapter tablistHider;
private Management management; private Management management;
private CommandHandler commandHandler = null; private CommandHandler commandHandler;
private PermissionsManager permsMan = null; private PermissionsManager permsMan;
private NewSetting newSettings; private NewSetting newSettings;
private Messages messages; private Messages messages;
private JsonCache playerBackup; private JsonCache playerBackup;
private PasswordSecurity passwordSecurity; private PasswordSecurity passwordSecurity;
private DataSource database; private DataSource database;
private IpAddressManager ipAddressManager;
private PluginHooks pluginHooks;
private SpawnLoader spawnLoader;
private AntiBot antiBot;
private boolean autoPurging;
/** /**
* Get the plugin's instance. * Get the plugin's instance.
@ -248,16 +248,24 @@ public class AuthMe extends JavaPlugin {
return; return;
} }
pluginHooks = new PluginHooks(server.getPluginManager());
MigrationService.changePlainTextToSha256(newSettings, database, new SHA256()); MigrationService.changePlainTextToSha256(newSettings, database, new SHA256());
passwordSecurity = new PasswordSecurity(getDataSource(), newSettings.getProperty(SecuritySettings.PASSWORD_HASH), passwordSecurity = new PasswordSecurity(getDataSource(), newSettings, Bukkit.getPluginManager());
Bukkit.getPluginManager(), newSettings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH)); ipAddressManager = new IpAddressManager(newSettings);
// Initialize spawn loader
spawnLoader = new SpawnLoader(getDataFolder(), newSettings, pluginHooks);
// Set up the permissions manager and command handler // Set up the permissions manager and command handler
permsMan = initializePermissionsManager(); permsMan = initializePermissionsManager();
commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings); commandHandler = initializeCommandHandler(permsMan, messages, passwordSecurity, newSettings, ipAddressManager,
pluginHooks, spawnLoader, antiBot);
// Setup otherAccounts file // AntiBot delay
this.otherAccounts = OtherAccounts.getInstance(); BukkitService bukkitService = new BukkitService(this);
antiBot = new AntiBot(newSettings, messages, permsMan, bukkitService);
// Set up Metrics // Set up Metrics
MetricsStarter.setupMetrics(plugin, newSettings); MetricsStarter.setupMetrics(plugin, newSettings);
@ -265,25 +273,12 @@ public class AuthMe extends JavaPlugin {
// Set console filter // Set console filter
setupConsoleFilter(); setupConsoleFilter();
// AntiBot delay
AntiBot.setupAntiBotService();
// Download and load GeoIp.dat file if absent // Download and load GeoIp.dat file if absent
GeoLiteAPI.isDataAvailable(); GeoLiteAPI.isDataAvailable();
// Set up the mail API // Set up the mail API
setupMailApi(); setupMailApi();
// Hooks
// Check Combat Tag Plus Version
checkCombatTagPlus();
// Check Multiverse
checkMultiverse();
// Check Essentials
checkEssentials();
// Check if the ProtocolLib is available. If so we could listen for // Check if the ProtocolLib is available. If so we could listen for
// inventory protection // inventory protection
checkProtocolLib(); checkProtocolLib();
@ -297,26 +292,24 @@ public class AuthMe extends JavaPlugin {
playerBackup = new JsonCache(); playerBackup = new JsonCache();
// Set the DataManager // Set the DataManager
dataManager = new DataManager(this); dataManager = new DataManager(this, pluginHooks);
// Set up the new API // Set up the new API
setupApi(); setupApi();
// Set up the management // Set up the management
management = new Management(this, newSettings); ProcessService processService = new ProcessService(newSettings, messages, this, database, ipAddressManager,
passwordSecurity, pluginHooks, spawnLoader);
management = new Management(this, processService, database, PlayerCache.getInstance());
// Set up the BungeeCord hook // Set up the BungeeCord hook
setupBungeeCordHook(); setupBungeeCordHook(newSettings, ipAddressManager);
// Reload support hook // Reload support hook
reloadSupportHook(); reloadSupportHook();
// Register event listeners // Register event listeners
registerEventListeners(); registerEventListeners(messages, database, management, pluginHooks, spawnLoader, antiBot);
// Purge on start if enabled
autoPurge();
// Start Email recall task if needed // Start Email recall task if needed
scheduleRecallEmailTask(); scheduleRecallEmailTask();
@ -330,6 +323,26 @@ public class AuthMe extends JavaPlugin {
// Successful message // Successful message
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " correctly enabled!"); ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " correctly enabled!");
// Purge on start if enabled
runAutoPurge();
}
/**
* Reload certain components.
*
* @throws Exception if an error occurs
*/
public void reload() throws Exception {
newSettings.reload();
// We do not change database type for consistency issues, but we'll output a note in the logs
if (!newSettings.getProperty(DatabaseSettings.BACKEND).equals(database.getType())) {
ConsoleLogger.info("Note: cannot change database type during /authme reload");
}
database.reload();
messages.reload(newSettings.getMessagesFile());
passwordSecurity.reload(newSettings);
spawnLoader.initialize(newSettings);
} }
/** /**
@ -361,15 +374,16 @@ public class AuthMe extends JavaPlugin {
/** /**
* Register all event listeners. * Register all event listeners.
*/ */
private void registerEventListeners() { private void registerEventListeners(Messages messages, DataSource dataSource, Management management,
PluginHooks pluginHooks, SpawnLoader spawnLoader, AntiBot antiBot) {
// Get the plugin manager instance // Get the plugin manager instance
PluginManager pluginManager = server.getPluginManager(); PluginManager pluginManager = server.getPluginManager();
// Register event listeners // Register event listeners
pluginManager.registerEvents(new AuthMePlayerListener(this), this); pluginManager.registerEvents(new AuthMePlayerListener(this, messages, dataSource, antiBot, management), this);
pluginManager.registerEvents(new AuthMeBlockListener(), this); pluginManager.registerEvents(new AuthMeBlockListener(), this);
pluginManager.registerEvents(new AuthMeEntityListener(), this); pluginManager.registerEvents(new AuthMeEntityListener(), this);
pluginManager.registerEvents(new AuthMeServerListener(this), this); pluginManager.registerEvents(new AuthMeServerListener(this, messages, pluginHooks, spawnLoader), this);
// Try to register 1.6 player listeners // Try to register 1.6 player listeners
try { try {
@ -407,20 +421,23 @@ public class AuthMe extends JavaPlugin {
/** /**
* Set up the BungeeCord hook. * Set up the BungeeCord hook.
*/ */
private void setupBungeeCordHook() { private void setupBungeeCordHook(NewSetting settings, IpAddressManager ipAddressManager) {
if (newSettings.getProperty(HooksSettings.BUNGEECORD)) { if (settings.getProperty(HooksSettings.BUNGEECORD)) {
Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
Bukkit.getMessenger().registerIncomingPluginChannel(this, "BungeeCord", new BungeeCordMessage(this)); Bukkit.getMessenger().registerIncomingPluginChannel(
this, "BungeeCord", new BungeeCordMessage(this, ipAddressManager));
} }
} }
private CommandHandler initializeCommandHandler(PermissionsManager permissionsManager, Messages messages, private CommandHandler initializeCommandHandler(PermissionsManager permissionsManager, Messages messages,
PasswordSecurity passwordSecurity, NewSetting settings) { PasswordSecurity passwordSecurity, NewSetting settings,
IpAddressManager ipAddressManager, PluginHooks pluginHooks,
SpawnLoader spawnLoader, AntiBot antiBot) {
HelpProvider helpProvider = new HelpProvider(permissionsManager, settings.getProperty(HELP_HEADER)); HelpProvider helpProvider = new HelpProvider(permissionsManager, settings.getProperty(HELP_HEADER));
Set<CommandDescription> baseCommands = CommandInitializer.buildCommands(); Set<CommandDescription> baseCommands = CommandInitializer.buildCommands();
CommandMapper mapper = new CommandMapper(baseCommands, permissionsManager); CommandMapper mapper = new CommandMapper(baseCommands, permissionsManager);
CommandService commandService = new CommandService( CommandService commandService = new CommandService(this, mapper, helpProvider, messages, passwordSecurity,
this, mapper, helpProvider, messages, passwordSecurity, permissionsManager, settings); permissionsManager, settings, ipAddressManager, pluginHooks, spawnLoader, antiBot);
return new CommandHandler(commandService); return new CommandHandler(commandService);
} }
@ -455,8 +472,10 @@ public class AuthMe extends JavaPlugin {
private NewSetting createNewSetting() { private NewSetting createNewSetting() {
File configFile = new File(getDataFolder(), "config.yml"); File configFile = new File(getDataFolder(), "config.yml");
return SettingsMigrationService.copyFileFromResource(configFile, "config.yml") PropertyMap properties = SettingsFieldRetriever.getAllPropertyFields();
? new NewSetting(configFile, getDataFolder()) SettingsMigrationService migrationService = new SettingsMigrationService();
return FileUtils.copyFileFromResource(configFile, "config.yml")
? new NewSetting(configFile, getDataFolder(), properties, migrationService)
: null; : null;
} }
@ -546,6 +565,8 @@ public class AuthMe extends JavaPlugin {
* *
* @param settings The settings instance * @param settings The settings instance
* *
* @throws ClassNotFoundException if no driver could be found for the datasource
* @throws SQLException when initialization of a SQL datasource failed
* @see AuthMe#database * @see AuthMe#database
*/ */
public void setupDatabase(NewSetting settings) throws ClassNotFoundException, SQLException { public void setupDatabase(NewSetting settings) throws ClassNotFoundException, SQLException {
@ -600,80 +621,20 @@ public class AuthMe extends JavaPlugin {
return manager; return manager;
} }
/**
* Get the permissions manager instance.
*
* @return Permissions Manager instance.
*/
public PermissionsManager getPermissionsManager() {
return this.permsMan;
}
// Set the console filter to remove the passwords // Set the console filter to remove the passwords
private void setLog4JFilter() { private void setLog4JFilter() {
Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
@Override @Override
public void run() { public void run() {
org.apache.logging.log4j.core.Logger coreLogger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger(); org.apache.logging.log4j.core.Logger logger;
coreLogger.addFilter(new Log4JFilter()); logger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger();
logger.addFilter(new Log4JFilter());
logger = (org.apache.logging.log4j.core.Logger) LogManager.getLogger("net.minecraft");
logger.addFilter(new Log4JFilter());
} }
}); });
} }
// Get the Multiverse plugin
public void checkMultiverse() {
if (Settings.multiverse && server.getPluginManager().isPluginEnabled("Multiverse-Core")) {
try {
multiverse = (MultiverseCore) server.getPluginManager().getPlugin("Multiverse-Core");
ConsoleLogger.info("Hooked correctly with Multiverse-Core");
} catch (Exception | NoClassDefFoundError ignored) {
multiverse = null;
}
} else {
multiverse = null;
}
}
// Get the Essentials plugin
public void checkEssentials() {
if (server.getPluginManager().isPluginEnabled("Essentials")) {
try {
ess = (Essentials) server.getPluginManager().getPlugin("Essentials");
ConsoleLogger.info("Hooked correctly with Essentials");
} catch (Exception | NoClassDefFoundError ignored) {
ess = null;
}
} else {
ess = null;
}
if (server.getPluginManager().isPluginEnabled("EssentialsSpawn")) {
try {
essentialsSpawn = new EssSpawn().getLocation();
ConsoleLogger.info("Hooked correctly with EssentialsSpawn");
} catch (Exception e) {
essentialsSpawn = null;
ConsoleLogger.showError("Can't read the /plugins/Essentials/spawn.yml file!");
}
} else {
essentialsSpawn = null;
}
}
// Check the presence of CombatTag
public void checkCombatTagPlus() {
if (server.getPluginManager().isPluginEnabled("CombatTagPlus")) {
try {
combatTagPlus = (CombatTagPlus) server.getPluginManager().getPlugin("CombatTagPlus");
ConsoleLogger.info("Hooked correctly with CombatTagPlus");
} catch (Exception | NoClassDefFoundError ignored) {
combatTagPlus = null;
}
} else {
combatTagPlus = null;
}
}
// Check the presence of the ProtocolLib plugin // Check the presence of the ProtocolLib plugin
public void checkProtocolLib() { public void checkProtocolLib() {
if (!server.getPluginManager().isPluginEnabled("ProtocolLib")) { if (!server.getPluginManager().isPluginEnabled("ProtocolLib")) {
@ -716,7 +677,10 @@ public class AuthMe extends JavaPlugin {
} }
String name = player.getName().toLowerCase(); String name = player.getName().toLowerCase();
if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead() && Settings.isSaveQuitLocationEnabled) { if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead() && Settings.isSaveQuitLocationEnabled) {
final PlayerAuth auth = new PlayerAuth(player.getName().toLowerCase(), player.getLocation().getX(), player.getLocation().getY(), player.getLocation().getZ(), player.getWorld().getName(), player.getName()); final PlayerAuth auth = PlayerAuth.builder()
.name(player.getName().toLowerCase())
.realName(player.getName())
.location(player.getLocation()).build();
database.updateQuitLoc(auth); database.updateQuitLoc(auth);
} }
if (LimboCache.getInstance().hasLimboPlayer(name)) { if (LimboCache.getInstance().hasLimboPlayer(name)) {
@ -726,8 +690,8 @@ public class AuthMe extends JavaPlugin {
} }
Utils.addNormal(player, limbo.getGroup()); Utils.addNormal(player, limbo.getGroup());
player.setOp(limbo.getOperator()); player.setOp(limbo.isOperator());
limbo.getTimeoutTaskId().cancel(); limbo.getTimeoutTask().cancel();
LimboCache.getInstance().deleteLimboPlayer(name); LimboCache.getInstance().deleteLimboPlayer(name);
if (this.playerBackup.doesCacheExist(player)) { if (this.playerBackup.doesCacheExist(player)) {
this.playerBackup.removeCache(player); this.playerBackup.removeCache(player);
@ -747,34 +711,43 @@ public class AuthMe extends JavaPlugin {
} }
// Purge inactive players from the database, as defined in the configuration // Purge inactive players from the database, as defined in the configuration
private void autoPurge() { private void runAutoPurge() {
if (!Settings.usePurge) { if (!newSettings.getProperty(PurgeSettings.USE_AUTO_PURGE) || autoPurging) {
return; return;
} }
Calendar calendar = Calendar.getInstance(); autoPurging = true;
calendar.add(Calendar.DATE, -(Settings.purgeDelay)); server.getScheduler().runTaskAsynchronously(this, new Runnable() {
long until = calendar.getTimeInMillis(); @Override
List<String> cleared = database.autoPurgeDatabase(until); public void run() {
if (CollectionUtils.isEmpty(cleared)) { ConsoleLogger.info("AutoPurging the Database...");
return; Calendar calendar = Calendar.getInstance();
} calendar.add(Calendar.DATE, -newSettings.getProperty(PurgeSettings.DAYS_BEFORE_REMOVE_PLAYER));
ConsoleLogger.info("AutoPurging the Database: " + cleared.size() + " accounts removed!"); long until = calendar.getTimeInMillis();
if (Settings.purgeEssentialsFile && this.ess != null) List<String> cleared = database.autoPurgeDatabase(until);
dataManager.purgeEssentials(cleared); if (CollectionUtils.isEmpty(cleared)) {
if (Settings.purgePlayerDat) return;
dataManager.purgeDat(cleared); }
if (Settings.purgeLimitedCreative) ConsoleLogger.info("AutoPurging the Database: " + cleared.size() + " accounts removed!");
dataManager.purgeLimitedCreative(cleared); if (newSettings.getProperty(PurgeSettings.REMOVE_ESSENTIALS_FILES) && pluginHooks.isEssentialsAvailable())
if (Settings.purgeAntiXray) dataManager.purgeEssentials(cleared);
dataManager.purgeAntiXray(cleared); if (newSettings.getProperty(PurgeSettings.REMOVE_PLAYER_DAT))
if (Settings.purgePermissions) dataManager.purgeDat(cleared);
dataManager.purgePermissions(cleared); if (newSettings.getProperty(PurgeSettings.REMOVE_LIMITED_CREATIVE_INVENTORIES))
dataManager.purgeLimitedCreative(cleared);
if (newSettings.getProperty(PurgeSettings.REMOVE_ANTI_XRAY_FILE))
dataManager.purgeAntiXray(cleared);
if (newSettings.getProperty(PurgeSettings.REMOVE_PERMISSIONS))
dataManager.purgePermissions(cleared);
ConsoleLogger.info("AutoPurge Finished!");
autoPurging = false;
}
});
} }
// Return the spawn location of a player // Return the spawn location of a player
@Deprecated @Deprecated
public Location getSpawnLocation(Player player) { public Location getSpawnLocation(Player player) {
return Spawn.getInstance().getSpawnLocation(player); return spawnLoader.getSpawnLocation(player);
} }
private void scheduleRecallEmailTask() { private void scheduleRecallEmailTask() {
@ -786,7 +759,7 @@ public class AuthMe extends JavaPlugin {
public void run() { public void run() {
for (PlayerAuth auth : database.getLoggedPlayers()) { for (PlayerAuth auth : database.getLoggedPlayers()) {
String email = auth.getEmail(); String email = auth.getEmail();
if (email == null || email.isEmpty() || email.equalsIgnoreCase("your@email.com")) { if (StringUtils.isEmpty(email) || email.equalsIgnoreCase("your@email.com")) {
Player player = Utils.getPlayer(auth.getRealName()); Player player = Utils.getPlayer(auth.getRealName());
if (player != null) { if (player != null) {
messages.send(player, MessageKey.ADD_EMAIL_MESSAGE); messages.send(player, MessageKey.ADD_EMAIL_MESSAGE);
@ -794,77 +767,37 @@ public class AuthMe extends JavaPlugin {
} }
} }
} }
}, 1, 1200 * Settings.delayRecall); }, 1, 1200 * newSettings.getProperty(EmailSettings.DELAY_RECALL));
} }
public String replaceAllInfo(String message, Player player) { public String replaceAllInfo(String message, Player player) {
String playersOnline = Integer.toString(Utils.getOnlinePlayers().size()); String playersOnline = Integer.toString(Utils.getOnlinePlayers().size());
String ipAddress = ipAddressManager.getPlayerIp(player);
return message return message
.replace("&", "\u00a7") .replace("&", "\u00a7")
.replace("{PLAYER}", player.getName()) .replace("{PLAYER}", player.getName())
.replace("{ONLINE}", playersOnline) .replace("{ONLINE}", playersOnline)
.replace("{MAXPLAYERS}", Integer.toString(server.getMaxPlayers())) .replace("{MAXPLAYERS}", Integer.toString(server.getMaxPlayers()))
.replace("{IP}", getIP(player)) .replace("{IP}", ipAddress)
.replace("{LOGINS}", Integer.toString(PlayerCache.getInstance().getLogged())) .replace("{LOGINS}", Integer.toString(PlayerCache.getInstance().getLogged()))
.replace("{WORLD}", player.getWorld().getName()) .replace("{WORLD}", player.getWorld().getName())
.replace("{SERVER}", server.getServerName()) .replace("{SERVER}", server.getServerName())
.replace("{VERSION}", server.getBukkitVersion()) .replace("{VERSION}", server.getBukkitVersion())
.replace("{COUNTRY}", GeoLiteAPI.getCountryName(getIP(player))); .replace("{COUNTRY}", GeoLiteAPI.getCountryName(ipAddress));
}
/**
* 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();
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)) {
ip = realIp.get(name);
}
return ip;
} }
public boolean isLoggedIp(String name, String ip) { public boolean isLoggedIp(String name, String ip) {
int count = 0; int count = 0;
for (Player player : Utils.getOnlinePlayers()) { for (Player player : Utils.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(getIP(player)) && database.isLogged(player.getName().toLowerCase()) && !player.getName().equalsIgnoreCase(name)) if (ip.equalsIgnoreCase(ipAddressManager.getPlayerIp(player))
count++; && database.isLogged(player.getName().toLowerCase())
&& !player.getName().equalsIgnoreCase(name)) {
++count;
}
} }
return count >= Settings.getMaxLoginPerIp; return count >= Settings.getMaxLoginPerIp;
} }
public boolean hasJoinedIp(String name, String ip) {
int count = 0;
for (Player player : Utils.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(getIP(player)) && !player.getName().equalsIgnoreCase(name))
count++;
}
return count >= Settings.getMaxJoinPerIp;
}
/** /**
* Handle Bukkit commands. * Handle Bukkit commands.
* *
@ -888,6 +821,15 @@ public class AuthMe extends JavaPlugin {
return commandHandler.processCommand(sender, commandLabel, args); return commandHandler.processCommand(sender, commandLabel, args);
} }
/**
* Get the permissions manager instance.
*
* @return Permissions Manager instance.
*/
public PermissionsManager getPermissionsManager() {
return this.permsMan;
}
/** /**
* Return the management instance. * Return the management instance.
* *
@ -905,4 +847,8 @@ public class AuthMe extends JavaPlugin {
return passwordSecurity; return passwordSecurity;
} }
public PluginHooks getPluginHooks() {
return pluginHooks;
}
} }

View File

@ -1,161 +1,112 @@
package fr.xephi.authme; package fr.xephi.authme;
import java.io.File; import fr.xephi.authme.hooks.PluginHooks;
import java.util.List; import fr.xephi.authme.permission.PermissionsManager;
import java.util.concurrent.Callable; import fr.xephi.authme.settings.properties.PurgeSettings;
import java.util.concurrent.ExecutorService; import fr.xephi.authme.util.Utils;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import fr.xephi.authme.permission.PermissionsManager; import java.io.File;
import fr.xephi.authme.settings.Settings; import java.util.ArrayList;
import fr.xephi.authme.util.Utils; import java.util.List;
/** /**
*/ */
public class DataManager { public class DataManager {
public final AuthMe plugin; private final AuthMe plugin;
private final PluginHooks pluginHooks;
/** /**
* Constructor for DataManager. * Constructor for DataManager.
* *
* @param plugin AuthMe * @param plugin The plugin instance
* @param pluginHooks Plugin hooks instance
*/ */
public DataManager(AuthMe plugin) { public DataManager(AuthMe plugin, PluginHooks pluginHooks) {
this.plugin = plugin; this.plugin = plugin;
this.pluginHooks = pluginHooks;
} }
/** private List<OfflinePlayer> getOfflinePlayers(List<String> names) {
* Method getOfflinePlayer. List<OfflinePlayer> result = new ArrayList<>();
* for (OfflinePlayer op : Bukkit.getOfflinePlayers()) {
* @param name String for (String name : names) {
* if (name.equalsIgnoreCase(op.getName())) {
* @return OfflinePlayer result.add(op);
*/
public synchronized OfflinePlayer getOfflinePlayer(final String name) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<OfflinePlayer> result = executor.submit(new Callable<OfflinePlayer>() {
public synchronized OfflinePlayer call() throws Exception {
OfflinePlayer result = null;
try {
for (OfflinePlayer op : Bukkit.getOfflinePlayers())
if (op.getName().equalsIgnoreCase(name)) {
result = op;
break;
}
} catch (Exception ignored) {
} }
return result;
} }
});
try {
return result.get();
} catch (Exception e) {
return (null);
} finally {
executor.shutdown();
} }
return result;
} }
/** public void purgeAntiXray(List<String> cleared) {
* Method purgeAntiXray.
*
* @param cleared List of String
*/
public synchronized void purgeAntiXray(List<String> cleared) {
int i = 0; int i = 0;
for (String name : cleared) { File dataFolder = new File("." + File.separator + "plugins" + File.separator + "AntiXRayData"
try { + File.separator + "PlayerData");
org.bukkit.OfflinePlayer player = getOfflinePlayer(name); if (!dataFolder.exists() || !dataFolder.isDirectory()) {
if (player == null) return;
continue; }
String playerName = player.getName(); for (String file : dataFolder.list()) {
File playerFile = new File("." + File.separator + "plugins" + File.separator + "AntiXRayData" + File.separator + "PlayerData" + File.separator + playerName); if (cleared.contains(file.toLowerCase())) {
if (playerFile.exists()) { File playerFile = new File(dataFolder, file);
//noinspection ResultOfMethodCallIgnored if (playerFile.exists() && playerFile.delete()) {
playerFile.delete();
i++; i++;
} }
} catch (Exception ignored) {
} }
} }
ConsoleLogger.info("AutoPurgeDatabase : Remove " + i + " AntiXRayData Files"); ConsoleLogger.info("AutoPurge: Removed " + i + " AntiXRayData Files");
} }
/**
* Method purgeLimitedCreative.
*
* @param cleared List of String
*/
public synchronized void purgeLimitedCreative(List<String> cleared) { public synchronized void purgeLimitedCreative(List<String> cleared) {
int i = 0; int i = 0;
for (String name : cleared) { File dataFolder = new File("." + File.separator + "plugins" + File.separator + "LimitedCreative"
try { + File.separator + "inventories");
org.bukkit.OfflinePlayer player = getOfflinePlayer(name); for (String file : dataFolder.list()) {
if (player == null) String name = file;
continue; int idx;
String playerName = player.getName(); idx = file.lastIndexOf("_creative.yml");
File playerFile = new File("." + File.separator + "plugins" + File.separator + "LimitedCreative" + File.separator + "inventories" + File.separator + playerName + ".yml"); if (idx != -1) {
if (playerFile.exists()) { name = name.substring(0, idx);
//noinspection ResultOfMethodCallIgnored } else {
playerFile.delete(); idx = file.lastIndexOf("_adventure.yml");
i++; if (idx != -1) {
} name = name.substring(0, idx);
playerFile = new File("." + File.separator + "plugins" + File.separator + "LimitedCreative" + File.separator + "inventories" + File.separator + playerName + "_creative.yml"); } else {
if (playerFile.exists()) { idx = file.lastIndexOf(".yml");
//noinspection ResultOfMethodCallIgnored if (idx != -1) {
playerFile.delete(); name = name.substring(0, idx);
i++;
}
playerFile = new File("." + File.separator + "plugins" + File.separator + "LimitedCreative" + File.separator + "inventories" + File.separator + playerName + "_adventure.yml");
if (playerFile.exists()) {
//noinspection ResultOfMethodCallIgnored
playerFile.delete();
i++;
}
} catch (Exception ignored) {
}
}
ConsoleLogger.info("AutoPurgeDatabase : Remove " + i + " LimitedCreative Survival, Creative and Adventure files");
}
/**
* Method purgeDat.
*
* @param cleared List of String
*/
public synchronized void purgeDat(List<String> cleared) {
int i = 0;
for (String name : cleared) {
try {
org.bukkit.OfflinePlayer player = getOfflinePlayer(name);
if (player == null) {
continue;
}
try {
File playerFile = new File(plugin.getServer().getWorldContainer() + File.separator + Settings.defaultWorld + File.separator + "players" + File.separator + player.getUniqueId() + ".dat");
//noinspection ResultOfMethodCallIgnored
playerFile.delete();
i++;
} catch (Exception ignore) {
File playerFile = new File(plugin.getServer().getWorldContainer() + File.separator + Settings.defaultWorld + File.separator + "players" + File.separator + player.getName() + ".dat");
if (playerFile.exists()) {
//noinspection ResultOfMethodCallIgnored
playerFile.delete();
i++;
} }
} }
} catch (Exception ignore) { }
if (name.equals(file)) {
continue;
}
if (cleared.contains(name.toLowerCase())) {
File dataFile = new File(dataFolder, file);
if (dataFile.exists() && dataFile.delete()) {
i++;
}
} }
} }
ConsoleLogger.info("AutoPurgeDatabase : Remove " + i + " .dat Files"); ConsoleLogger.info("AutoPurge: Removed " + i + " LimitedCreative Survival, Creative and Adventure files");
}
public synchronized void purgeDat(List<String> cleared) {
int i = 0;
File dataFolder = new File(plugin.getServer().getWorldContainer()
+ File.separator + plugin.getSettings().getProperty(PurgeSettings.DEFAULT_WORLD)
+ File.separator + "players");
List<OfflinePlayer> offlinePlayers = getOfflinePlayers(cleared);
for (OfflinePlayer player : offlinePlayers) {
File playerFile = new File(dataFolder, Utils.getUUIDorName(player) + ".dat");
if (playerFile.delete()) {
i++;
}
}
ConsoleLogger.info("AutoPurge: Removed " + i + " .dat Files");
} }
/** /**
@ -163,107 +114,49 @@ public class DataManager {
* *
* @param cleared List of String * @param cleared List of String
*/ */
@SuppressWarnings("deprecation")
public void purgeEssentials(List<String> cleared) { public void purgeEssentials(List<String> cleared) {
int i = 0; int i = 0;
for (String name : cleared) { File essentialsDataFolder = pluginHooks.getEssentialsDataFolder();
try { if (essentialsDataFolder == null) {
File playerFile = new File(plugin.ess.getDataFolder() + File.separator + "userdata" + File.separator + plugin.getServer().getOfflinePlayer(name).getUniqueId() + ".yml"); ConsoleLogger.info("Cannot purge Essentials: plugin is not loaded");
//noinspection ResultOfMethodCallIgnored return;
playerFile.delete(); }
final File userDataFolder = new File(essentialsDataFolder, "userdata");
List<OfflinePlayer> offlinePlayers = getOfflinePlayers(cleared);
for (OfflinePlayer player : offlinePlayers) {
File playerFile = new File(userDataFolder, Utils.getUUIDorName(player) + ".yml");
if (playerFile.exists() && playerFile.delete()) {
i++; i++;
} catch (Exception e) {
File playerFile = new File(plugin.ess.getDataFolder() + File.separator + "userdata" + File.separator + name + ".yml");
if (playerFile.exists()) {
//noinspection ResultOfMethodCallIgnored
playerFile.delete();
i++;
}
} }
} }
ConsoleLogger.info("AutoPurgeDatabase : Remove " + i + " EssentialsFiles");
ConsoleLogger.info("AutoPurge: Removed " + i + " EssentialsFiles");
} }
// TODO: What is this method for? Is it correct? // TODO: What is this method for? Is it correct?
// TODO: Make it work with OfflinePlayers group data.
/**
* @param cleared Cleared players.
*/
public synchronized void purgePermissions(List<String> cleared) { public synchronized void purgePermissions(List<String> cleared) {
// Get the permissions manager, and make sure it's valid // Get the permissions manager, and make sure it's valid
PermissionsManager permsMan = this.plugin.getPermissionsManager(); PermissionsManager permsMan = plugin.getPermissionsManager();
if (permsMan == null) if (permsMan == null) {
ConsoleLogger.showError("Unable to access permissions manager instance!"); ConsoleLogger.showError("Unable to access permissions manager instance!");
assert permsMan != null; return;
}
int i = 0; int i = 0;
for (String name : cleared) { for (String name : cleared) {
try { permsMan.removeAllGroups(getOnlinePlayerLower(name));
permsMan.removeAllGroups(this.getOnlinePlayerLower(name.toLowerCase())); i++;
i++;
} catch (Exception ignored) {
}
} }
ConsoleLogger.info("AutoPurgeDatabase : Removed " + i + "permissions"); ConsoleLogger.info("AutoPurge: Removed permissions from " + i + " player(s).");
/*int i = 0;
for (String name : cleared) {
try {
OfflinePlayer p = this.getOfflinePlayer(name);
for (String group : permission.getPlayerGroups((Player) p)) {
permission.playerRemoveGroup(null, p, group);
}
i++;
} catch (Exception e) {
}
}
ConsoleLogger.info("AutoPurgeDatabase : Remove " + i + " Permissions");*/
} }
/** private Player getOnlinePlayerLower(String name) {
* Method isOnline.
*
* @param player Player
* @param name String
*
* @return boolean
*/
public boolean isOnline(Player player, final String name) {
if (player.isOnline())
return true;
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Boolean> result = executor.submit(new Callable<Boolean>() {
@Override
public synchronized Boolean call() throws Exception {
for (OfflinePlayer op : Utils.getOnlinePlayers())
if (op.getName().equalsIgnoreCase(name)) {
return true;
}
return false;
}
});
try {
return result.get();
} catch (Exception e) {
return false;
} finally {
executor.shutdown();
}
}
/**
* Method getOnlinePlayerLower.
*
* @param name String
*
* @return Player
*/
public Player getOnlinePlayerLower(String name) {
name = name.toLowerCase(); name = name.toLowerCase();
for (Player player : Utils.getOnlinePlayers()) { for (Player player : Utils.getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(name)) if (player.getName().equalsIgnoreCase(name)) {
return player; return player;
}
} }
return null; return null;
} }

View File

@ -13,7 +13,10 @@ import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
/** /**
* The current API of AuthMe. * The current API of AuthMe. Recommended method of retrieving the API object:
* <code>
* NewAPI authmeApi = NewAPI.getInstance();
* </code>
*/ */
public class NewAPI { public class NewAPI {
@ -23,7 +26,7 @@ public class NewAPI {
/** /**
* Constructor for NewAPI. * Constructor for NewAPI.
* *
* @param plugin AuthMe * @param plugin The AuthMe plugin instance
*/ */
public NewAPI(AuthMe plugin) { public NewAPI(AuthMe plugin) {
this.plugin = plugin; this.plugin = plugin;
@ -32,16 +35,17 @@ public class NewAPI {
/** /**
* Constructor for NewAPI. * Constructor for NewAPI.
* *
* @param server Server * @param server The server instance
*/ */
public NewAPI(Server server) { public NewAPI(Server server) {
this.plugin = (AuthMe) server.getPluginManager().getPlugin("AuthMe"); this.plugin = (AuthMe) server.getPluginManager().getPlugin("AuthMe");
} }
/** /**
* Hook into AuthMe * Get the API object for AuthMe.
* *
* @return The API object * @return The API object, or null if the AuthMe plugin instance could not be retrieved
* from the server environment
*/ */
public static NewAPI getInstance() { public static NewAPI getInstance() {
if (singleton != null) { if (singleton != null) {
@ -65,11 +69,20 @@ public class NewAPI {
return plugin; return plugin;
} }
/**
* Gather the version number of the plugin.
* This can be used to determine whether certain API features are available or not.
*
* @return Plugin version identifier as a string.
*/
public String getPluginVersion() {
return AuthMe.getPluginVersion();
}
/** /**
* Return whether the given player is authenticated. * Return whether the given player is authenticated.
* *
* @param player The player to verify * @param player The player to verify
*
* @return true if the player is authenticated * @return true if the player is authenticated
*/ */
public boolean isAuthenticated(Player player) { public boolean isAuthenticated(Player player) {
@ -77,18 +90,22 @@ public class NewAPI {
} }
/** /**
* @param player a Player * Check whether the given player is an NPC.
* *
* @return true if player is a npc * @param player The player to verify
* @return true if the player is an npc
*/ */
public boolean isNPC(Player player) { public boolean isNPC(Player player) {
return Utils.isNPC(player); return Utils.isNPC(player);
} }
/** /**
* @param player a Player * Check whether the given player is unrestricted. For such players, AuthMe will not require
* them to authenticate.
* *
* @param player The player to verify
* @return true if the player is unrestricted * @return true if the player is unrestricted
* @see fr.xephi.authme.settings.properties.RestrictionSettings#UNRESTRICTED_NAMES
*/ */
public boolean isUnrestricted(Player player) { public boolean isUnrestricted(Player player) {
return Utils.isUnrestricted(player); return Utils.isUnrestricted(player);
@ -97,30 +114,21 @@ public class NewAPI {
/** /**
* Get the last location of a player. * Get the last location of a player.
* *
* @param player Player The player to process * @param player The player to process
*
* @return Location The location of the player * @return Location The location of the player
*/ */
public Location getLastLocation(Player player) { public Location getLastLocation(Player player) {
try { PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName());
PlayerAuth auth = PlayerCache.getInstance().getAuth(player.getName()); if (auth != null) {
return new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
if (auth != null) {
return new Location(Bukkit.getWorld(auth.getWorld()), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ());
} else {
return null;
}
} catch (NullPointerException ex) {
return null;
} }
return null;
} }
/** /**
* Return whether the player is registered. * Return whether the player is registered.
* *
* @param playerName The player name to check * @param playerName The player name to check
*
* @return true if player is registered, false otherwise * @return true if player is registered, false otherwise
*/ */
public boolean isRegistered(String playerName) { public boolean isRegistered(String playerName) {
@ -133,7 +141,6 @@ public class NewAPI {
* *
* @param playerName The player to check the password for * @param playerName The player to check the password for
* @param passwordToCheck The password to check * @param passwordToCheck The password to check
*
* @return true if the password is correct, false otherwise * @return true if the password is correct, false otherwise
*/ */
public boolean checkPassword(String playerName, String passwordToCheck) { public boolean checkPassword(String playerName, String passwordToCheck) {
@ -141,11 +148,10 @@ public class NewAPI {
} }
/** /**
* Register a player. * Register a player with the given password.
* *
* @param playerName The player to register * @param playerName The player to register
* @param password The password to register the player with * @param password The password to register the player with
*
* @return true if the player was registered successfully * @return true if the player was registered successfully
*/ */
public boolean registerPlayer(String playerName, String password) { public boolean registerPlayer(String playerName, String password) {
@ -163,7 +169,7 @@ public class NewAPI {
} }
/** /**
* Force a player to login. * Force a player to login, i.e. the player is logged in without needing his password.
* *
* @param player The player to log in * @param player The player to log in
*/ */
@ -181,7 +187,7 @@ public class NewAPI {
} }
/** /**
* Force a player to register. * Register a player with the given password.
* *
* @param player The player to register * @param player The player to register
* @param password The password to use * @param password The password to use
@ -191,7 +197,7 @@ public class NewAPI {
} }
/** /**
* Force a player to unregister. * Unregister a player from AuthMe.
* *
* @param player The player to unregister * @param player The player to unregister
*/ */

View File

@ -0,0 +1,81 @@
package fr.xephi.authme.cache;
import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.SecuritySettings;
import java.util.concurrent.ConcurrentHashMap;
/**
* Manager for the handling of captchas.
*/
public class CaptchaManager {
private final int threshold;
private final int captchaLength;
private final ConcurrentHashMap<String, Integer> playerCounts;
private final ConcurrentHashMap<String, String> captchaCodes;
public CaptchaManager(NewSetting settings) {
this.playerCounts = new ConcurrentHashMap<>();
this.captchaCodes = new ConcurrentHashMap<>();
this.threshold = settings.getProperty(SecuritySettings.MAX_LOGIN_TRIES_BEFORE_CAPTCHA);
this.captchaLength = settings.getProperty(SecuritySettings.CAPTCHA_LENGTH);
}
public void increaseCount(String player) {
String playerLower = player.toLowerCase();
Integer currentCount = playerCounts.get(playerLower);
if (currentCount == null) {
playerCounts.put(playerLower, 1);
} else {
playerCounts.put(playerLower, currentCount + 1);
}
}
/**
* Return whether the given player is required to solve a captcha.
*
* @param player The player to verify
* @return True if the player has to solve a captcha, false otherwise
*/
public boolean isCaptchaRequired(String player) {
Integer count = playerCounts.get(player.toLowerCase());
return count != null && count >= threshold;
}
/**
* Return the captcha code for the player. Creates one if none present, so call only after
* checking with {@link #isCaptchaRequired}.
*
* @param player The player
* @return The code required for the player
*/
public String getCaptchaCode(String player) {
String code = captchaCodes.get(player.toLowerCase());
if (code == null) {
code = RandomString.generate(captchaLength);
captchaCodes.put(player.toLowerCase(), code);
}
return code;
}
/**
* Return whether the supplied code is correct for the given player.
*
* @param player The player to check
* @param code The supplied code
* @return True if the code matches or if no captcha is required for the player, false otherwise
*/
public boolean checkCode(String player, String code) {
String savedCode = captchaCodes.get(player.toLowerCase());
if (savedCode == null) {
return true;
} else if (savedCode.equalsIgnoreCase(code)) {
captchaCodes.remove(player.toLowerCase());
return true;
}
return false;
}
}

View File

@ -0,0 +1,99 @@
package fr.xephi.authme.cache;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.entity.Player;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
/**
* Stateful manager for looking up IP address appropriately, including caching.
*/
public class IpAddressManager {
/** Whether or not to use the VeryGames API for IP lookups. */
private final boolean useVeryGamesIpCheck;
/** Cache for lookups via the VeryGames API. */
private final ConcurrentHashMap<String, String> ipCache;
/**
* Constructor.
*
* @param settings The settings instance
*/
public IpAddressManager(NewSetting settings) {
this.useVeryGamesIpCheck = settings.getProperty(HooksSettings.ENABLE_VERYGAMES_IP_CHECK);
this.ipCache = new ConcurrentHashMap<>();
}
/**
* Return the player's IP address. If enabled in the settings, the IP address returned by the
* VeryGames API will be returned.
*
* @param player The player to look up
* @return The IP address of the player
*/
public String getPlayerIp(Player player) {
if (useVeryGamesIpCheck) {
final String playerName = player.getName().toLowerCase();
final String cachedValue = ipCache.get(playerName);
if (cachedValue != null) {
return cachedValue;
}
final String plainIp = player.getAddress().getAddress().getHostAddress();
String veryGamesResult = getVeryGamesIp(plainIp, player.getAddress().getPort());
if (veryGamesResult != null) {
ipCache.put(playerName, veryGamesResult);
return veryGamesResult;
}
}
return player.getAddress().getAddress().getHostAddress();
}
/**
* Add a player to the IP address cache.
*
* @param player The player to add or update the cache entry for
* @param ip The IP address to add
*/
public void addCache(String player, String ip) {
if (useVeryGamesIpCheck) {
ipCache.put(player.toLowerCase(), ip);
}
}
/**
* Remove a player's cache entry.
*
* @param player The player to remove
*/
public void removeCache(String player) {
if (useVeryGamesIpCheck) {
ipCache.remove(player.toLowerCase());
}
}
// returns null if IP could not be looked up
private String getVeryGamesIp(final String plainIp, final int port) {
final String sUrl = String.format("http://monitor-1.verygames.net/api/?action=ipclean-real-ip"
+ "&out=raw&ip=%s&port=%d", plainIp, port);
try {
String result = Resources.toString(new URL(sUrl), Charsets.UTF_8);
if (!StringUtils.isEmpty(result) && !result.contains("error")) {
return result;
}
} catch (IOException e) {
ConsoleLogger.logException("Could not fetch Very Games API with URL '" + sUrl + "':", e);
}
return null;
}
}

View File

@ -8,20 +8,24 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* AuthMe player data.
*/ */
public class PlayerAuth { public class PlayerAuth {
/** The player's name in lowercase, e.g. "xephi". */
private String nickname; private String nickname;
/** The player's name in the correct casing, e.g. "Xephi". */
private String realName;
private HashedPassword password; private HashedPassword password;
private String email;
private String ip; private String ip;
private int groupId;
private long lastLogin; private long lastLogin;
// Fields storing the player's quit location
private double x; private double x;
private double y; private double y;
private double z; private double z;
private String world; private String world;
private int groupId;
private String email;
private String realName;
/** /**
* @param serialized String * @param serialized String
@ -31,92 +35,19 @@ public class PlayerAuth {
} }
/** /**
* Constructor for PlayerAuth. * Constructor. Instantiate objects with the {@link #builder() builder}.
* *
* @param nickname String * @param nickname all lowercase name of the player
* @param ip String * @param password password
* @param lastLogin long * @param groupId the group id
* @param realName String * @param ip the associated ip address
*/ * @param lastLogin player's last login (timestamp)
public PlayerAuth(String nickname, String ip, long lastLogin, String realName) { * @param x quit location: x coordinate
this(nickname, new HashedPassword(""), -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName); * @param y quit location: y coordinate
} * @param z quit location: z coordinate
* @param world quit location: world name
/** * @param email the associated email
* Constructor for PlayerAuth. * @param realName the player's name with proper casing
*
* @param nickname String
* @param x double
* @param y double
* @param z double
* @param world String
* @param realName String
*/
public PlayerAuth(String nickname, double x, double y, double z, String world, String realName) {
this(nickname, new HashedPassword(""), -1, "127.0.0.1", System.currentTimeMillis(), x, y, z, world,
"your@email.com", realName);
}
/**
* Constructor for PlayerAuth.
*
* @param nickname String
* @param hash String
* @param ip String
* @param lastLogin long
* @param realName String
*/
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, String realName) {
this(nickname, new HashedPassword(hash), -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
}
/**
* Constructor for PlayerAuth.
*
* @param nickname String
* @param hash String
* @param ip String
* @param lastLogin long
* @param email String
* @param realName String
*/
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, String email, String realName) {
this(nickname, new HashedPassword(hash), -1, ip, lastLogin, 0, 0, 0, "world", email, realName);
}
/**
* Constructor for PlayerAuth.
*
* @param nickname String
* @param hash String
* @param ip String
* @param lastLogin long
* @param x double
* @param y double
* @param z double
* @param world String
* @param email String
* @param realName String
*/
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, double x, double y, double z,
String world, String email, String realName) {
this(nickname, new HashedPassword(hash), -1, ip, lastLogin, x, y, z, world, email, realName);
}
/**
* Constructor for PlayerAuth.
*
* @param nickname String
* @param password String
* @param groupId int
* @param ip String
* @param lastLogin long
* @param x double
* @param y double
* @param z double
* @param world String
* @param email String
* @param realName String
*/ */
private PlayerAuth(String nickname, HashedPassword password, int groupId, String ip, long lastLogin, private PlayerAuth(String nickname, HashedPassword password, int groupId, String ip, long lastLogin,
double x, double y, double z, String world, String email, String realName) { double x, double y, double z, String world, String email, String realName) {
@ -133,24 +64,6 @@ public class PlayerAuth {
this.realName = realName; this.realName = realName;
} }
/**
* Method set.
*
* @param auth PlayerAuth
*/
public void set(PlayerAuth auth) {
this.setEmail(auth.getEmail());
this.setPassword(auth.getPassword());
this.setIp(auth.getIp());
this.setLastLogin(auth.getLastLogin());
this.setNickname(auth.getNickname());
this.setQuitLocX(auth.getQuitLocX());
this.setQuitLocY(auth.getQuitLocY());
this.setQuitLocZ(auth.getQuitLocZ());
this.setWorld(auth.getWorld());
this.setRealName(auth.getRealName());
}
public void setNickname(String nickname) { public void setNickname(String nickname) {
this.nickname = nickname.toLowerCase(); this.nickname = nickname.toLowerCase();

View File

@ -35,29 +35,6 @@ public class JsonCache {
.create(); .create();
} }
public void createCache(Player player, PlayerData playerData) {
if (player == null) {
return;
}
String name = player.getName().toLowerCase();
File file = new File(cacheDir, name + File.separator + "cache.json");
if (file.exists()) {
return;
}
if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
return;
}
try {
String data = gson.toJson(playerData);
Files.touch(file);
Files.write(data, file, Charsets.UTF_8);
} catch (IOException e) {
ConsoleLogger.writeStackTrace(e);
}
}
public PlayerData readCache(Player player) { public PlayerData readCache(Player player) {
String name = player.getName().toLowerCase(); String name = player.getName().toLowerCase();
File file = new File(cacheDir, name + File.separator + "cache.json"); File file = new File(cacheDir, name + File.separator + "cache.json");

View File

@ -16,8 +16,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class LimboCache { public class LimboCache {
private volatile static LimboCache singleton; private volatile static LimboCache singleton;
public final ConcurrentHashMap<String, LimboPlayer> cache; private final ConcurrentHashMap<String, LimboPlayer> cache;
public final AuthMe plugin; private final AuthMe plugin;
private final JsonCache jsonCache; private final JsonCache jsonCache;
/** /**
@ -84,7 +84,7 @@ public class LimboCache {
checkNotNull(name); checkNotNull(name);
name = name.toLowerCase(); name = name.toLowerCase();
if (cache.containsKey(name)) { if (cache.containsKey(name)) {
cache.get(name).clearTask(); cache.get(name).clearTasks();
cache.remove(name); cache.remove(name);
} }
} }

View File

@ -4,14 +4,16 @@ import org.bukkit.Location;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
/** /**
* Represents a player which is not logged in and keeps track of certain states (like OP status, flying)
* which may be revoked from the player until he has logged in or registered.
*/ */
public class LimboPlayer { public class LimboPlayer {
private final String name; private final String name;
private final boolean fly; private final boolean fly;
private Location loc = null; private Location loc = null;
private BukkitTask timeoutTaskId = null; private BukkitTask timeoutTask = null;
private BukkitTask messageTaskId = null; private BukkitTask messageTask = null;
private boolean operator = false; private boolean operator = false;
private String group; private String group;
@ -25,36 +27,36 @@ public class LimboPlayer {
} }
/** /**
* Method getName. * Return the name of the player.
* *
* @return String * @return The player's name
*/ */
public String getName() { public String getName() {
return name; return name;
} }
/** /**
* Method getLoc. * Return the player's original location.
* *
* @return Location * @return The player's location
*/ */
public Location getLoc() { public Location getLoc() {
return loc; return loc;
} }
/** /**
* Method getOperator. * Return whether the player is an operator or not (i.e. whether he is an OP).
* *
* @return boolean * @return True if the player has OP status, false otherwise
*/ */
public boolean getOperator() { public boolean isOperator() {
return operator; return operator;
} }
/** /**
* Method getGroup. * Return the player's permissions group.
* *
* @return String * @return The permissions group the player belongs to
*/ */
public String getGroup() { public String getGroup() {
return group; return group;
@ -64,54 +66,61 @@ public class LimboPlayer {
return fly; return fly;
} }
public BukkitTask getTimeoutTaskId() {
return timeoutTaskId;
}
/** /**
* Method setTimeoutTaskId. * Return the timeout task, which kicks the player if he hasn't registered or logged in
* after a configurable amount of time.
* *
* @param i BukkitTask * @return The timeout task associated to the player
*/ */
public void setTimeoutTaskId(BukkitTask i) { public BukkitTask getTimeoutTask() {
if (this.timeoutTaskId != null) { return timeoutTask;
this.timeoutTaskId.cancel();
}
this.timeoutTaskId = i;
} }
/** /**
* Method getMessageTaskId. * Set the timeout task of the player. The timeout task kicks the player after a configurable
* amount of time if he hasn't logged in or registered.
* *
* @return BukkitTask * @param timeoutTask The task to set
*/ */
public BukkitTask getMessageTaskId() { public void setTimeoutTask(BukkitTask timeoutTask) {
return messageTaskId; if (this.timeoutTask != null) {
this.timeoutTask.cancel();
}
this.timeoutTask = timeoutTask;
} }
/** /**
* Method setMessageTaskId. * Return the message task reminding the player to log in or register.
* *
* @param messageTaskId BukkitTask * @return The task responsible for sending the message regularly
*/ */
public void setMessageTaskId(BukkitTask messageTaskId) { public BukkitTask getMessageTask() {
if (this.messageTaskId != null) { return messageTask;
this.messageTaskId.cancel();
}
this.messageTaskId = messageTaskId;
} }
/** /**
* Method clearTask. * Set the messages task responsible for telling the player to log in or register.
*
* @param messageTask The message task to set
*/ */
public void clearTask() { public void setMessageTask(BukkitTask messageTask) {
if (messageTaskId != null) { if (this.messageTask != null) {
messageTaskId.cancel(); this.messageTask.cancel();
} }
messageTaskId = null; this.messageTask = messageTask;
if (timeoutTaskId != null) { }
timeoutTaskId.cancel();
/**
* Clears all tasks associated to the player.
*/
public void clearTasks() {
if (messageTask != null) {
messageTask.cancel();
} }
timeoutTaskId = null; messageTask = null;
if (timeoutTask != null) {
timeoutTask.cancel();
}
timeoutTask = null;
} }
} }

View File

@ -92,7 +92,7 @@ public final class CommandInitializer {
.description("Enforce login player") .description("Enforce login player")
.detailedDescription("Enforce the specified player to login.") .detailedDescription("Enforce the specified player to login.")
.withArgument("player", "Online player name", true) .withArgument("player", "Online player name", true)
.permissions(OP_ONLY, PlayerPermission.CAN_LOGIN_BE_FORCED) .permissions(OP_ONLY, AdminPermission.FORCE_LOGIN)
.executableCommand(new ForceLoginCommand()) .executableCommand(new ForceLoginCommand())
.build(); .build();
@ -159,7 +159,7 @@ public final class CommandInitializer {
.labels("getip", "ip") .labels("getip", "ip")
.description("Get player's IP") .description("Get player's IP")
.detailedDescription("Get the IP address of the specified online player.") .detailedDescription("Get the IP address of the specified online player.")
.withArgument("player", "Player Name", false) .withArgument("player", "Player name", false)
.permissions(OP_ONLY, AdminPermission.GET_IP) .permissions(OP_ONLY, AdminPermission.GET_IP)
.executableCommand(new GetIpCommand()) .executableCommand(new GetIpCommand())
.build(); .build();
@ -170,7 +170,6 @@ public final class CommandInitializer {
.labels("spawn", "home") .labels("spawn", "home")
.description("Teleport to spawn") .description("Teleport to spawn")
.detailedDescription("Teleport to the spawn.") .detailedDescription("Teleport to the spawn.")
.withArgument("player", "Player Name", false)
.permissions(OP_ONLY, AdminPermission.SPAWN) .permissions(OP_ONLY, AdminPermission.SPAWN)
.executableCommand(new SpawnCommand()) .executableCommand(new SpawnCommand())
.build(); .build();

View File

@ -1,18 +1,22 @@
package fr.xephi.authme.command; package fr.xephi.authme.command;
import fr.xephi.authme.AntiBot;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.help.HelpProvider; import fr.xephi.authme.command.help.HelpProvider;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.process.Management; import fr.xephi.authme.process.Management;
import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property; import fr.xephi.authme.settings.domain.Property;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import java.io.File;
import java.util.List; import java.util.List;
/** /**
@ -28,6 +32,10 @@ public class CommandService {
private final PasswordSecurity passwordSecurity; private final PasswordSecurity passwordSecurity;
private final PermissionsManager permissionsManager; private final PermissionsManager permissionsManager;
private final NewSetting settings; private final NewSetting settings;
private final IpAddressManager ipAddressManager;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
private final AntiBot antiBot;
/** /**
* Constructor. * Constructor.
@ -39,10 +47,14 @@ public class CommandService {
* @param passwordSecurity The Password Security instance * @param passwordSecurity The Password Security instance
* @param permissionsManager The permissions manager * @param permissionsManager The permissions manager
* @param settings The settings manager * @param settings The settings manager
* @param ipAddressManager The IP address manager
* @param pluginHooks The plugin hooks instance
* @param spawnLoader The spawn loader
*/ */
public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages, public CommandService(AuthMe authMe, CommandMapper commandMapper, HelpProvider helpProvider, Messages messages,
PasswordSecurity passwordSecurity, PermissionsManager permissionsManager, PasswordSecurity passwordSecurity, PermissionsManager permissionsManager, NewSetting settings,
NewSetting settings) { IpAddressManager ipAddressManager, PluginHooks pluginHooks, SpawnLoader spawnLoader,
AntiBot antiBot) {
this.authMe = authMe; this.authMe = authMe;
this.messages = messages; this.messages = messages;
this.helpProvider = helpProvider; this.helpProvider = helpProvider;
@ -50,6 +62,10 @@ public class CommandService {
this.passwordSecurity = passwordSecurity; this.passwordSecurity = passwordSecurity;
this.permissionsManager = permissionsManager; this.permissionsManager = permissionsManager;
this.settings = settings; this.settings = settings;
this.ipAddressManager = ipAddressManager;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
this.antiBot = antiBot;
} }
/** /**
@ -163,15 +179,6 @@ public class CommandService {
return messages.retrieve(key); return messages.retrieve(key);
} }
/**
* Change the messages instance to retrieve messages from the given file.
*
* @param file The new file to read messages from
*/
public void reloadMessages(File file) {
messages.reload(file);
}
/** /**
* Retrieve the given property's value. * Retrieve the given property's value.
* *
@ -192,4 +199,24 @@ public class CommandService {
return settings; return settings;
} }
public IpAddressManager getIpAddressManager() {
return ipAddressManager;
}
public PlayerCache getPlayerCache() {
return PlayerCache.getInstance();
}
public PluginHooks getPluginHooks() {
return pluginHooks;
}
public SpawnLoader getSpawnLoader() {
return spawnLoader;
}
public AntiBot getAntiBot() {
return antiBot;
}
} }

View File

@ -8,6 +8,9 @@ import java.util.List;
public final class CommandUtils { public final class CommandUtils {
private CommandUtils() {
}
public static int getMinNumberOfArguments(CommandDescription command) { public static int getMinNumberOfArguments(CommandDescription command) {
int mandatoryArguments = 0; int mandatoryArguments = 0;
for (CommandArgumentDescription argument : command.getArguments()) { for (CommandArgumentDescription argument : command.getArguments()) {

View File

@ -2,7 +2,6 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
@ -41,6 +40,8 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
commandService.send(sender, MessageKey.INVALID_PASSWORD_LENGTH); commandService.send(sender, MessageKey.INVALID_PASSWORD_LENGTH);
return; return;
} }
// TODO #602 20160312: The UNSAFE_PASSWORDS should be all lowercase
// -> introduce a lowercase String list property type
if (commandService.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(playerPassLowerCase)) { if (commandService.getProperty(SecuritySettings.UNSAFE_PASSWORDS).contains(playerPassLowerCase)) {
commandService.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR); commandService.send(sender, MessageKey.PASSWORD_UNSAFE_ERROR);
return; return;
@ -53,8 +54,8 @@ public class ChangePasswordAdminCommand implements ExecutableCommand {
public void run() { public void run() {
DataSource dataSource = commandService.getDataSource(); DataSource dataSource = commandService.getDataSource();
PlayerAuth auth = null; PlayerAuth auth = null;
if (PlayerCache.getInstance().isAuthenticated(playerNameLowerCase)) { if (commandService.getPlayerCache().isAuthenticated(playerNameLowerCase)) {
auth = PlayerCache.getInstance().getAuth(playerNameLowerCase); auth = commandService.getPlayerCache().getAuth(playerNameLowerCase);
} else if (dataSource.isAuthAvailable(playerNameLowerCase)) { } else if (dataSource.isAuthAvailable(playerNameLowerCase)) {
auth = dataSource.getAuth(playerNameLowerCase); auth = dataSource.getAuth(playerNameLowerCase);
} }

View File

@ -1,27 +1,22 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand; import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
/**
* Teleports the player to the first spawn.
*/
public class FirstSpawnCommand extends PlayerCommand { public class FirstSpawnCommand extends PlayerCommand {
@Override @Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) { public void runCommand(Player player, List<String> arguments, CommandService commandService) {
// Make sure the command executor is a player if (commandService.getSpawnLoader().getFirstSpawn() != null) {
try { player.teleport(commandService.getSpawnLoader().getFirstSpawn());
if (Spawn.getInstance().getFirstSpawn() != null) { } else {
player.teleport(Spawn.getInstance().getFirstSpawn()); player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
} else {
player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
}
} catch (NullPointerException ex) {
// TODO ljacqu 20151119: Catching NullPointerException is never a good idea. Find what can cause one instead
ConsoleLogger.showError(ex.getMessage());
} }
} }
} }

View File

@ -8,13 +8,16 @@ import org.bukkit.command.CommandSender;
import java.util.List; import java.util.List;
/**
* Returns a player's email.
*/
public class GetEmailCommand implements ExecutableCommand { public class GetEmailCommand implements ExecutableCommand {
@Override @Override
public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) { public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) {
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
PlayerAuth auth = commandService.getDataSource().getAuth(playerName.toLowerCase()); PlayerAuth auth = commandService.getDataSource().getAuth(playerName);
if (auth == null) { if (auth == null) {
commandService.send(sender, MessageKey.UNKNOWN_USER); commandService.send(sender, MessageKey.UNKNOWN_USER);
} else { } else {

View File

@ -1,21 +1,18 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import java.util.List; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.util.Utils;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import fr.xephi.authme.AuthMe; import java.util.List;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.util.Utils;
public class GetIpCommand implements ExecutableCommand { public class GetIpCommand implements ExecutableCommand {
@Override @Override
public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) { public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) {
final AuthMe plugin = AuthMe.getInstance();
// Get the player query // Get the player query
String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName();
@ -25,9 +22,12 @@ public class GetIpCommand implements ExecutableCommand {
return; return;
} }
// TODO ljacqu 20151212: Revise the messages (actual IP vs. real IP...?) sender.sendMessage(player.getName() + "'s IP is: " + player.getAddress().getAddress().getHostAddress()
sender.sendMessage(player.getName() + "'s actual IP is : " + player.getAddress().getAddress().getHostAddress()
+ ":" + player.getAddress().getPort()); + ":" + player.getAddress().getPort());
sender.sendMessage(player.getName() + "'s real IP is : " + plugin.getIP(player));
if (commandService.getProperty(HooksSettings.ENABLE_VERYGAMES_IP_CHECK)) {
sender.sendMessage(player.getName() + "'s real IP is: "
+ commandService.getIpAddressManager().getPlayerIp(player));
}
} }
} }

View File

@ -10,6 +10,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
/** /**
* Returns the last login date of the given user.
*/ */
public class LastLoginCommand implements ExecutableCommand { public class LastLoginCommand implements ExecutableCommand {
@ -18,23 +19,24 @@ public class LastLoginCommand implements ExecutableCommand {
// Get the player // Get the player
String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName(); String playerName = (arguments.size() >= 1) ? arguments.get(0) : sender.getName();
PlayerAuth auth = commandService.getDataSource().getAuth(playerName.toLowerCase()); PlayerAuth auth = commandService.getDataSource().getAuth(playerName);
if (auth == null) { if (auth == null) {
commandService.send(sender, MessageKey.USER_NOT_REGISTERED); commandService.send(sender, MessageKey.USER_NOT_REGISTERED);
return; return;
} }
// Get the last login date // Get the last login date
long lastLogin = auth.getLastLogin(); final long lastLogin = auth.getLastLogin();
final long diff = System.currentTimeMillis() - lastLogin; final long diff = System.currentTimeMillis() - lastLogin;
final String lastLoginMessage = (int) (diff / 86400000) + " days " + (int) (diff / 3600000 % 24) + " hours " final String lastLoginMessage = (int) (diff / 86400000) + " days "
+ (int) (diff / 60000 % 60) + " mins " + (int) (diff / 1000 % 60) + " secs"; + (int) (diff / 3600000 % 24) + " hours "
+ (int) (diff / 60000 % 60) + " mins "
+ (int) (diff / 1000 % 60) + " secs";
Date date = new Date(lastLogin); Date date = new Date(lastLogin);
// Show the player status // Show the player status
sender.sendMessage("[AuthMe] " + playerName + " last login: " + date.toString()); sender.sendMessage("[AuthMe] " + playerName + " last login: " + date.toString());
sender.sendMessage("[AuthMe] The player " + auth.getNickname() + " last logged in " sender.sendMessage("[AuthMe] The player " + playerName + " last logged in " + lastLoginMessage + " ago.");
+ lastLoginMessage + " ago.");
sender.sendMessage("[AuthMe] Last Player's IP: " + auth.getIp()); sender.sendMessage("[AuthMe] Last Player's IP: " + auth.getIp());
} }
} }

View File

@ -3,19 +3,23 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PurgeSettings;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* Command for purging data of banned players. Depending on the settings
* it purges (deletes) data from third-party plugins as well.
*/
public class PurgeBannedPlayersCommand implements ExecutableCommand { public class PurgeBannedPlayersCommand implements ExecutableCommand {
@Override @Override
public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) { public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) {
// AuthMe plugin instance // AuthMe plugin instance
final AuthMe plugin = AuthMe.getInstance(); final AuthMe plugin = commandService.getAuthMe();
// Get the list of banned players // Get the list of banned players
List<String> bannedPlayers = new ArrayList<>(); List<String> bannedPlayers = new ArrayList<>();
@ -24,14 +28,15 @@ public class PurgeBannedPlayersCommand implements ExecutableCommand {
} }
// Purge the banned players // Purge the banned players
plugin.getDataSource().purgeBanned(bannedPlayers); commandService.getDataSource().purgeBanned(bannedPlayers);
if (Settings.purgeEssentialsFile && plugin.ess != null) if (commandService.getProperty(PurgeSettings.REMOVE_ESSENTIALS_FILES)
&& commandService.getPluginHooks().isEssentialsAvailable())
plugin.dataManager.purgeEssentials(bannedPlayers); plugin.dataManager.purgeEssentials(bannedPlayers);
if (Settings.purgePlayerDat) if (commandService.getProperty(PurgeSettings.REMOVE_PLAYER_DAT))
plugin.dataManager.purgeDat(bannedPlayers); plugin.dataManager.purgeDat(bannedPlayers);
if (Settings.purgeLimitedCreative) if (commandService.getProperty(PurgeSettings.REMOVE_LIMITED_CREATIVE_INVENTORIES))
plugin.dataManager.purgeLimitedCreative(bannedPlayers); plugin.dataManager.purgeLimitedCreative(bannedPlayers);
if (Settings.purgeAntiXray) if (commandService.getProperty(PurgeSettings.REMOVE_ANTI_XRAY_FILE))
plugin.dataManager.purgeAntiXray(bannedPlayers); plugin.dataManager.purgeAntiXray(bannedPlayers);
// Show a status message // Show a status message

View File

@ -3,20 +3,23 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PurgeSettings;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
/**
* Command for purging the data of players which have not been since for a given number
* of days. Depending on the settings, this removes player data in third-party plugins as well.
*/
public class PurgeCommand implements ExecutableCommand { public class PurgeCommand implements ExecutableCommand {
private static final int MINIMUM_LAST_SEEN_DAYS = 30;
@Override @Override
public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) { public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) {
// AuthMe plugin instance
AuthMe plugin = AuthMe.getInstance();
// Get the days parameter // Get the days parameter
String daysStr = arguments.get(0); String daysStr = arguments.get(0);
@ -30,8 +33,9 @@ public class PurgeCommand implements ExecutableCommand {
} }
// Validate the value // Validate the value
if (days < 30) { if (days < MINIMUM_LAST_SEEN_DAYS) {
sender.sendMessage(ChatColor.RED + "You can only purge data older than 30 days"); sender.sendMessage(ChatColor.RED + "You can only purge data older than "
+ MINIMUM_LAST_SEEN_DAYS + " days");
return; return;
} }
@ -47,13 +51,15 @@ public class PurgeCommand implements ExecutableCommand {
sender.sendMessage(ChatColor.GOLD + "Deleted " + purged.size() + " user accounts"); sender.sendMessage(ChatColor.GOLD + "Deleted " + purged.size() + " user accounts");
// Purge other data // Purge other data
if (Settings.purgeEssentialsFile && plugin.ess != null) AuthMe plugin = commandService.getAuthMe();
if (commandService.getProperty(PurgeSettings.REMOVE_ESSENTIALS_FILES) &&
commandService.getPluginHooks().isEssentialsAvailable())
plugin.dataManager.purgeEssentials(purged); plugin.dataManager.purgeEssentials(purged);
if (Settings.purgePlayerDat) if (commandService.getProperty(PurgeSettings.REMOVE_PLAYER_DAT))
plugin.dataManager.purgeDat(purged); plugin.dataManager.purgeDat(purged);
if (Settings.purgeLimitedCreative) if (commandService.getProperty(PurgeSettings.REMOVE_LIMITED_CREATIVE_INVENTORIES))
plugin.dataManager.purgeLimitedCreative(purged); plugin.dataManager.purgeLimitedCreative(purged);
if (Settings.purgeAntiXray) if (commandService.getProperty(PurgeSettings.REMOVE_ANTI_XRAY_FILE))
plugin.dataManager.purgeAntiXray(purged); plugin.dataManager.purgeAntiXray(purged);
// Show a status message // Show a status message

View File

@ -8,45 +8,39 @@ import org.bukkit.command.CommandSender;
import java.util.List; import java.util.List;
/**
* Removes the stored last position of a user or of all.
*/
public class PurgeLastPositionCommand implements ExecutableCommand { public class PurgeLastPositionCommand implements ExecutableCommand {
@Override @Override
public void executeCommand(final CommandSender sender, List<String> arguments, CommandService commandService) { public void executeCommand(final CommandSender sender, List<String> arguments, CommandService commandService) {
String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0); String playerName = arguments.isEmpty() ? sender.getName() : arguments.get(0);
String playerNameLowerCase = playerName.toLowerCase();
if (playerNameLowerCase.equalsIgnoreCase("*")) if ("*".equals(playerName)) {
{ for (PlayerAuth auth : commandService.getDataSource().getAllAuths()) {
for (PlayerAuth auth : commandService.getDataSource().getAllAuths()) resetLastPosition(auth);
{
// Set the last position
auth.setQuitLocX(0D);
auth.setQuitLocY(0D);
auth.setQuitLocZ(0D);
auth.setWorld("world");
commandService.getDataSource().updateQuitLoc(auth); commandService.getDataSource().updateQuitLoc(auth);
} }
sender.sendMessage("All players last position locations are now reset"); sender.sendMessage("All players last position locations are now reset");
} } else {
else
{
// Get the user auth and make sure the user exists // Get the user auth and make sure the user exists
PlayerAuth auth = commandService.getDataSource().getAuth(playerNameLowerCase); PlayerAuth auth = commandService.getDataSource().getAuth(playerName);
if (auth == null) { if (auth == null) {
commandService.send(sender, MessageKey.UNKNOWN_USER); commandService.send(sender, MessageKey.UNKNOWN_USER);
return; return;
} }
// Set the last position resetLastPosition(auth);
auth.setQuitLocX(0D);
auth.setQuitLocY(0D);
auth.setQuitLocZ(0D);
auth.setWorld("world");
commandService.getDataSource().updateQuitLoc(auth); commandService.getDataSource().updateQuitLoc(auth);
sender.sendMessage(playerName + "'s last position location is now reset");
// Show a status message
sender.sendMessage(playerNameLowerCase + "'s last position location is now reset");
} }
}
private static void resetLastPosition(PlayerAuth auth) {
auth.setQuitLocX(0d);
auth.setQuitLocY(0d);
auth.setQuitLocZ(0d);
auth.setWorld("world");
} }
} }

View File

@ -22,8 +22,8 @@ public class RegisterAdminCommand implements ExecutableCommand {
public void executeCommand(final CommandSender sender, List<String> arguments, public void executeCommand(final CommandSender sender, List<String> arguments,
final CommandService commandService) { final CommandService commandService) {
// Get the player name and password // Get the player name and password
final String playerName = arguments.get(0).toLowerCase(); final String playerName = arguments.get(0);
final String playerPass = arguments.get(1).toLowerCase(); final String playerPass = arguments.get(1);
final String playerNameLowerCase = playerName.toLowerCase(); final String playerNameLowerCase = playerName.toLowerCase();
final String playerPassLowerCase = playerPass.toLowerCase(); final String playerPassLowerCase = playerPass.toLowerCase();

View File

@ -5,7 +5,6 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import java.util.List; import java.util.List;
@ -19,13 +18,7 @@ public class ReloadCommand implements ExecutableCommand {
public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) { public void executeCommand(CommandSender sender, List<String> arguments, CommandService commandService) {
AuthMe plugin = commandService.getAuthMe(); AuthMe plugin = commandService.getAuthMe();
try { try {
commandService.getSettings().reload(); plugin.reload();
commandService.reloadMessages(commandService.getSettings().getMessagesFile());
Spawn.reload();
// TODO #432: We should not reload only certain plugin entities but actually reinitialize all elements,
// i.e. here in the future we might not have setupDatabase() but Authme.onEnable(), maybe after
// a call to some destructor method
plugin.setupDatabase(commandService.getSettings());
commandService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS); commandService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS);
} catch (Exception e) { } catch (Exception e) {
sender.sendMessage("Error occurred during reload of AuthMe: aborting"); sender.sendMessage("Error occurred during reload of AuthMe: aborting");

View File

@ -1,9 +1,7 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand; import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -12,14 +10,10 @@ public class SetFirstSpawnCommand extends PlayerCommand {
@Override @Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) { public void runCommand(Player player, List<String> arguments, CommandService commandService) {
try { if (commandService.getSpawnLoader().setFirstSpawn(player.getLocation())) {
if (Spawn.getInstance().setFirstSpawn(player.getLocation())) { player.sendMessage("[AuthMe] Correctly defined new first spawn point");
player.sendMessage("[AuthMe] Correctly defined new first spawn point"); } else {
} else { player.sendMessage("[AuthMe] SetFirstSpawn has failed, please retry");
player.sendMessage("[AuthMe] SetFirstSpawn has failed, please retry");
}
} catch (NullPointerException ex) {
ConsoleLogger.showError(ex.getMessage());
} }
} }
} }

View File

@ -1,9 +1,7 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand; import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -12,14 +10,10 @@ public class SetSpawnCommand extends PlayerCommand {
@Override @Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) { public void runCommand(Player player, List<String> arguments, CommandService commandService) {
try { if (commandService.getSpawnLoader().setSpawn(player.getLocation())) {
if (Spawn.getInstance().setSpawn(player.getLocation())) { player.sendMessage("[AuthMe] Correctly defined new spawn point");
player.sendMessage("[AuthMe] Correctly defined new spawn point"); } else {
} else { player.sendMessage("[AuthMe] SetSpawn has failed, please retry");
player.sendMessage("[AuthMe] SetSpawn has failed, please retry");
}
} catch (NullPointerException ex) {
ConsoleLogger.showError(ex.getMessage());
} }
} }
} }

View File

@ -1,9 +1,7 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.PlayerCommand; import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.settings.Spawn;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -12,14 +10,10 @@ public class SpawnCommand extends PlayerCommand {
@Override @Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) { public void runCommand(Player player, List<String> arguments, CommandService commandService) {
try { if (commandService.getSpawnLoader().getSpawn() != null) {
if (Spawn.getInstance().getSpawn() != null) { player.teleport(commandService.getSpawnLoader().getSpawn());
player.teleport(Spawn.getInstance().getSpawn()); } else {
} else { player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn");
player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn");
}
} catch (NullPointerException ex) {
ConsoleLogger.showError(ex.getMessage());
} }
} }
} }

View File

@ -18,8 +18,9 @@ public class SwitchAntiBotCommand implements ExecutableCommand {
@Override @Override
public void executeCommand(final CommandSender sender, List<String> arguments, CommandService commandService) { public void executeCommand(final CommandSender sender, List<String> arguments, CommandService commandService) {
AntiBot antiBot = commandService.getAntiBot();
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
sender.sendMessage("[AuthMe] AntiBot status: " + AntiBot.getAntiBotStatus().name()); sender.sendMessage("[AuthMe] AntiBot status: " + antiBot.getAntiBotStatus().name());
return; return;
} }
@ -27,10 +28,10 @@ public class SwitchAntiBotCommand implements ExecutableCommand {
// Enable or disable the mod // Enable or disable the mod
if ("ON".equalsIgnoreCase(newState)) { if ("ON".equalsIgnoreCase(newState)) {
AntiBot.overrideAntiBotStatus(true); antiBot.overrideAntiBotStatus(true);
sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!"); sender.sendMessage("[AuthMe] AntiBot Manual Override: enabled!");
} else if ("OFF".equalsIgnoreCase(newState)) { } else if ("OFF".equalsIgnoreCase(newState)) {
AntiBot.overrideAntiBotStatus(false); antiBot.overrideAntiBotStatus(false);
sender.sendMessage("[AuthMe] AntiBot Manual Override: disabled!"); sender.sendMessage("[AuthMe] AntiBot Manual Override: disabled!");
} else { } else {
sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!"); sender.sendMessage(ChatColor.DARK_RED + "Invalid AntiBot mode!");

View File

@ -8,6 +8,7 @@ import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
@ -59,14 +60,14 @@ public class UnregisterAdminCommand implements ExecutableCommand {
BukkitScheduler scheduler = sender.getServer().getScheduler(); BukkitScheduler scheduler = sender.getServer().getScheduler();
if (timeOut != 0) { if (timeOut != 0) {
BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, playerNameLowerCase, target), timeOut); BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, playerNameLowerCase, target), timeOut);
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setTimeoutTaskId(id); LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setTimeoutTask(id);
} }
LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTaskId( LimboCache.getInstance().getLimboPlayer(playerNameLowerCase).setMessageTask(
scheduler.runTask( scheduler.runTask(
plugin, new MessageTask(plugin, playerNameLowerCase, MessageKey.REGISTER_MESSAGE, interval) plugin, new MessageTask(plugin, playerNameLowerCase, MessageKey.REGISTER_MESSAGE, interval)
) )
); );
if (Settings.applyBlindEffect) { if (commandService.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2)); target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
} }
commandService.send(target, MessageKey.UNREGISTERED_SUCCESS); commandService.send(target, MessageKey.UNREGISTERED_SUCCESS);

View File

@ -3,7 +3,7 @@ package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.ExecutableCommand;
import org.bukkit.Bukkit; import fr.xephi.authme.util.Utils;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -71,9 +71,7 @@ public class VersionCommand implements ExecutableCommand {
* @return True if the player is online, false otherwise. * @return True if the player is online, false otherwise.
*/ */
private static boolean isPlayerOnline(String minecraftName) { private static boolean isPlayerOnline(String minecraftName) {
// Note ljacqu 20151121: Generally you should use Utils#getOnlinePlayers to retrieve the list of online players. for (Player player : Utils.getOnlinePlayers()) {
// If it's only used in a for-each loop such as here, it's fine. For other purposes, go through the Utils class.
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(minecraftName)) { if (player.getName().equalsIgnoreCase(minecraftName)) {
return true; return true;
} }

View File

@ -7,7 +7,6 @@ import fr.xephi.authme.command.PlayerCommand;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.security.RandomString; import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.settings.properties.SecuritySettings; import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.Wrapper;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -18,9 +17,8 @@ public class CaptchaCommand extends PlayerCommand {
public void runCommand(Player player, List<String> arguments, CommandService commandService) { public void runCommand(Player player, List<String> arguments, CommandService commandService) {
final String playerNameLowerCase = player.getName().toLowerCase(); final String playerNameLowerCase = player.getName().toLowerCase();
final String captcha = arguments.get(0); final String captcha = arguments.get(0);
Wrapper wrapper = Wrapper.getInstance(); final AuthMe plugin = commandService.getAuthMe();
final AuthMe plugin = wrapper.getAuthMe(); PlayerCache playerCache = PlayerCache.getInstance();
PlayerCache playerCache = wrapper.getPlayerCache();
// Command logic // Command logic
if (playerCache.isAuthenticated(playerNameLowerCase)) { if (playerCache.isAuthenticated(playerNameLowerCase)) {

View File

@ -8,7 +8,6 @@ import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.settings.properties.RestrictionSettings; import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings; import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.ChangePasswordTask; import fr.xephi.authme.task.ChangePasswordTask;
import fr.xephi.authme.util.Wrapper;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List; import java.util.List;
@ -24,8 +23,7 @@ public class ChangePasswordCommand extends PlayerCommand {
String newPassword = arguments.get(1); String newPassword = arguments.get(1);
String name = player.getName().toLowerCase(); String name = player.getName().toLowerCase();
Wrapper wrapper = Wrapper.getInstance(); final PlayerCache playerCache = commandService.getPlayerCache();
final PlayerCache playerCache = wrapper.getPlayerCache();
if (!playerCache.isAuthenticated(name)) { if (!playerCache.isAuthenticated(name)) {
commandService.send(player, MessageKey.NOT_LOGGED_IN); commandService.send(player, MessageKey.NOT_LOGGED_IN);
return; return;

View File

@ -7,6 +7,7 @@ import fr.xephi.authme.process.Management;
import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.RandomString; import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -17,7 +18,7 @@ public class RegisterCommand extends PlayerCommand {
@Override @Override
public void runCommand(Player player, List<String> arguments, CommandService commandService) { public void runCommand(Player player, List<String> arguments, CommandService commandService) {
if (Settings.getPasswordHash == HashAlgorithm.TWO_FACTOR) { if (commandService.getProperty(SecuritySettings.PASSWORD_HASH) == HashAlgorithm.TWO_FACTOR) {
//for two factor auth we don't need to check the usage //for two factor auth we don't need to check the usage
commandService.getManagement().performRegister(player, "", ""); commandService.getManagement().performRegister(player, "", "");
return; return;

View File

@ -31,27 +31,13 @@ public class CrazyLoginConverter implements Converter {
this.sender = sender; this.sender = sender;
} }
/**
* Method getInstance.
*
* @return CrazyLoginConverter
*/
public CrazyLoginConverter getInstance() {
return this;
}
/**
* Method run.
*
* @see java.lang.Runnable#run()
*/
@Override @Override
public void run() { public void run() {
String fileName = Settings.crazyloginFileName; String fileName = Settings.crazyloginFileName;
try { try {
File source = new File(AuthMe.getInstance().getDataFolder() + File.separator + fileName); File source = new File(AuthMe.getInstance().getDataFolder() + File.separator + fileName);
if (!source.exists()) { if (!source.exists()) {
sender.sendMessage("Error while trying to import datas, please put " + fileName + " in AuthMe folder!"); sender.sendMessage("Error while trying to import data, please put " + fileName + " in AuthMe folder!");
return; return;
} }
String line; String line;
@ -59,14 +45,17 @@ public class CrazyLoginConverter implements Converter {
while ((line = users.readLine()) != null) { while ((line = users.readLine()) != null) {
if (line.contains("|")) { if (line.contains("|")) {
String[] args = line.split("\\|"); String[] args = line.split("\\|");
if (args.length < 2) if (args.length < 2 || "name".equalsIgnoreCase(args[0])) {
continue; continue;
if (args[0].equalsIgnoreCase("name")) }
continue; String playerName = args[0];
String playerName = args[0].toLowerCase();
String psw = args[1]; String psw = args[1];
if (psw != null) { if (psw != null) {
PlayerAuth auth = new PlayerAuth(playerName, psw, "127.0.0.1", System.currentTimeMillis(), playerName); PlayerAuth auth = PlayerAuth.builder()
.name(playerName.toLowerCase())
.realName(playerName)
.password(psw, null)
.build();
database.saveAuth(auth); database.saveAuth(auth);
} }
} }

View File

@ -3,39 +3,51 @@ package fr.xephi.authme.converter;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.datasource.FlatFile;
import fr.xephi.authme.datasource.SQLite; import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.DatabaseSettings; import java.util.ArrayList;
import java.sql.SQLException; import java.util.List;
/** /**
* Mandatory migration from the deprecated flat file datasource to SQLite. * Mandatory migration from the deprecated flat file datasource to SQLite.
*/ */
public class ForceFlatToSqlite { public class ForceFlatToSqlite implements Converter {
private final DataSource database; private final DataSource source;
private final NewSetting settings; private final DataSource destination;
public ForceFlatToSqlite(DataSource database, NewSetting settings) { /**
this.database = database; * Constructor.
this.settings = settings; *
* @param source The datasource to convert (flatfile)
* @param destination The datasource to copy the data to (sqlite)
*/
public ForceFlatToSqlite(FlatFile source, DataSource destination) {
this.source = source;
this.destination = destination;
} }
public DataSource run() { /**
try { * Perform the conversion.
DataSource sqlite = new SQLite(settings); */
for (PlayerAuth auth : database.getAllAuths()) { @Override
auth.setRealName("Player"); public void run() {
sqlite.saveAuth(auth); List<String> skippedPlayers = new ArrayList<>();
for (PlayerAuth auth : source.getAllAuths()) {
if (destination.isAuthAvailable(auth.getNickname())) {
skippedPlayers.add(auth.getNickname());
} else {
destination.saveAuth(auth);
destination.updateQuitLoc(auth);
} }
settings.setProperty(DatabaseSettings.BACKEND, DataSourceType.SQLITE);
settings.save();
ConsoleLogger.info("Database successfully converted to sqlite!");
return sqlite;
} catch (SQLException | ClassNotFoundException e) {
ConsoleLogger.logException("Could not convert from Flatfile to SQLite:", e);
} }
return null;
if (!skippedPlayers.isEmpty()) {
ConsoleLogger.showError("Warning: skipped conversion for players which were already in SQLite: "
+ StringUtils.join(", ", skippedPlayers));
}
ConsoleLogger.info("Database successfully converted from " + source.getClass().getSimpleName()
+ " to " + destination.getClass().getSimpleName());
} }
} }

View File

@ -22,9 +22,9 @@ import java.util.Map.Entry;
*/ */
public class RakamakConverter implements Converter { public class RakamakConverter implements Converter {
public final AuthMe instance; private final AuthMe instance;
public final DataSource database; private final DataSource database;
public final CommandSender sender; private final CommandSender sender;
public RakamakConverter(AuthMe instance, CommandSender sender) { public RakamakConverter(AuthMe instance, CommandSender sender) {
this.instance = instance; this.instance = instance;

View File

@ -5,35 +5,46 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File; import java.io.File;
import static fr.xephi.authme.util.StringUtils.makePath;
public class RoyalAuthConverter implements Converter { public class RoyalAuthConverter implements Converter {
private static final String LAST_LOGIN_PATH = "timestamps.quit";
private static final String PASSWORD_PATH = "login.password";
private final AuthMe plugin; private final AuthMe plugin;
private final DataSource data; private final DataSource dataSource;
public RoyalAuthConverter(AuthMe plugin) { public RoyalAuthConverter(AuthMe plugin) {
this.plugin = plugin; this.plugin = plugin;
this.data = plugin.getDataSource(); this.dataSource = plugin.getDataSource();
} }
@Override @Override
public void run() { public void run() {
for (OfflinePlayer o : plugin.getServer().getOfflinePlayers()) { for (OfflinePlayer player : plugin.getServer().getOfflinePlayers()) {
try { try {
String name = o.getName().toLowerCase(); String name = player.getName().toLowerCase();
String sp = File.separator; File file = new File(makePath(".", "plugins", "RoyalAuth", "userdata", name + ".yml"));
File file = new File("." + sp + "plugins" + sp + "RoyalAuth" + sp + "userdata" + sp + name + ".yml");
if (data.isAuthAvailable(name)) if (dataSource.isAuthAvailable(name) || !file.exists()) {
continue; continue;
if (!file.exists()) }
continue; FileConfiguration configuration = YamlConfiguration.loadConfiguration(file);
RoyalAuthYamlReader ra = new RoyalAuthYamlReader(file); PlayerAuth auth = PlayerAuth.builder()
PlayerAuth auth = new PlayerAuth(name, ra.getHash(), "127.0.0.1", ra.getLastLogin(), "your@email.com", o.getName()); .name(name)
data.saveAuth(auth); .password(configuration.getString(PASSWORD_PATH), null)
.lastLogin(configuration.getLong(LAST_LOGIN_PATH))
.realName(player.getName())
.build();
dataSource.saveAuth(auth);
} catch (Exception e) { } catch (Exception e) {
ConsoleLogger.logException("Error while trying to import " + o.getName() + " RoyalAuth data", e); ConsoleLogger.logException("Error while trying to import " + player.getName() + " RoyalAuth data", e);
} }
} }
} }

View File

@ -1,22 +0,0 @@
package fr.xephi.authme.converter;
import fr.xephi.authme.settings.CustomConfiguration;
import java.io.File;
class RoyalAuthYamlReader extends CustomConfiguration {
public RoyalAuthYamlReader(File file) {
super(file);
load();
save();
}
public long getLastLogin() {
return getLong("timestamps.quit");
}
public String getHash() {
return getString("login.password");
}
}

View File

@ -12,6 +12,8 @@ import java.io.IOException;
import java.util.Scanner; import java.util.Scanner;
import java.util.UUID; import java.util.UUID;
import static fr.xephi.authme.util.StringUtils.makePath;
class vAuthFileReader { class vAuthFileReader {
private final AuthMe plugin; private final AuthMe plugin;
@ -28,7 +30,7 @@ class vAuthFileReader {
} }
public void convert() { public void convert() {
final File file = new File(plugin.getDataFolder().getParent() + File.separator + "vAuth" + File.separator + "passwords.yml"); final File file = new File(plugin.getDataFolder().getParent(), makePath("vAuth", "passwords.yml"));
Scanner scanner; Scanner scanner;
try { try {
scanner = new Scanner(file); scanner = new Scanner(file);
@ -46,9 +48,15 @@ class vAuthFileReader {
} }
if (pname == null) if (pname == null)
continue; continue;
auth = new PlayerAuth(pname.toLowerCase(), password, "127.0.0.1", System.currentTimeMillis(), "your@email.com", pname); auth = PlayerAuth.builder()
.name(pname.toLowerCase())
.realName(pname)
.password(password, null).build();
} else { } else {
auth = new PlayerAuth(name.toLowerCase(), password, "127.0.0.1", System.currentTimeMillis(), "your@email.com", name); auth = PlayerAuth.builder()
.name(name.toLowerCase())
.realName(name)
.password(password, null).build();
} }
database.saveAuth(auth); database.saveAuth(auth);
} }

View File

@ -50,7 +50,10 @@ class xAuthToFlat {
String pl = getIdPlayer(id); String pl = getIdPlayer(id);
String psw = getPassword(id); String psw = getPassword(id);
if (psw != null && !psw.isEmpty() && pl != null) { if (psw != null && !psw.isEmpty() && pl != null) {
PlayerAuth auth = new PlayerAuth(pl, psw, "192.168.0.1", 0, "your@email.com", pl); PlayerAuth auth = PlayerAuth.builder()
.name(pl.toLowerCase())
.realName(pl)
.password(psw, null).build();
database.saveAuth(auth); database.saveAuth(auth);
} }
} }
@ -69,7 +72,8 @@ class xAuthToFlat {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = String.format("SELECT `playername` FROM `%s` WHERE `id` = ?", xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT)); String sql = String.format("SELECT `playername` FROM `%s` WHERE `id` = ?",
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
ps = conn.prepareStatement(sql); ps = conn.prepareStatement(sql);
ps.setInt(1, id); ps.setInt(1, id);
rs = ps.executeQuery(); rs = ps.executeQuery();
@ -91,7 +95,8 @@ class xAuthToFlat {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = String.format("SELECT * FROM `%s`", xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT)); String sql = String.format("SELECT * FROM `%s`",
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
ps = conn.prepareStatement(sql); ps = conn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
while (rs.next()) { while (rs.next()) {
@ -112,7 +117,8 @@ class xAuthToFlat {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = String.format("SELECT `password`, `pwtype` FROM `%s` WHERE `id` = ?", xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT)); String sql = String.format("SELECT `password`, `pwtype` FROM `%s` WHERE `id` = ?",
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
ps = conn.prepareStatement(sql); ps = conn.prepareStatement(sql);
ps.setInt(1, accountId); ps.setInt(1, accountId);
rs = ps.executeQuery(); rs = ps.executeQuery();

View File

@ -64,6 +64,11 @@ public class CacheDataSource implements DataSource {
return cachedAuths; return cachedAuths;
} }
@Override
public void reload() {
source.reload();
}
@Override @Override
public synchronized boolean isAuthAvailable(String user) { public synchronized boolean isAuthAvailable(String user) {
return getAuth(user) != null; return getAuth(user) != null;
@ -162,12 +167,6 @@ public class CacheDataSource implements DataSource {
} }
} }
@Override
public void reload() { // unused method
source.reload();
cachedAuths.invalidateAll();
}
@Override @Override
public synchronized boolean updateEmail(final PlayerAuth auth) { public synchronized boolean updateEmail(final PlayerAuth auth) {
boolean result = source.updateEmail(auth); boolean result = source.updateEmail(auth);

View File

@ -121,8 +121,6 @@ public interface DataSource {
*/ */
void close(); void close();
void reload();
/** /**
* Method purgeBanned. * Method purgeBanned.
* *
@ -189,4 +187,9 @@ public interface DataSource {
boolean isEmailStored(String email); boolean isEmailStored(String email);
/**
* Reload the data source.
*/
void reload();
} }

View File

@ -1,5 +1,6 @@
package fr.xephi.authme.datasource; package fr.xephi.authme.datasource;
import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
@ -9,6 +10,7 @@ import fr.xephi.authme.settings.Settings;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
@ -18,6 +20,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* Deprecated flat file datasource. The only method guaranteed to work is {@link FlatFile#getAllAuths()}
* as to migrate the entries to {@link SQLite} when AuthMe starts.
*/ */
@Deprecated @Deprecated
public class FlatFile implements DataSource { public class FlatFile implements DataSource {
@ -42,7 +46,7 @@ public class FlatFile implements DataSource {
try { try {
source.createNewFile(); source.createNewFile();
} catch (IOException e) { } catch (IOException e) {
ConsoleLogger.showError(e.getMessage()); ConsoleLogger.logException("Cannot open flatfile", e);
if (Settings.isStopEnabled) { if (Settings.isStopEnabled) {
ConsoleLogger.showError("Can't use FLAT FILE... SHUTDOWN..."); ConsoleLogger.showError("Can't use FLAT FILE... SHUTDOWN...");
instance.getServer().shutdown(); instance.getServer().shutdown();
@ -50,10 +54,19 @@ public class FlatFile implements DataSource {
if (!Settings.isStopEnabled) { if (!Settings.isStopEnabled) {
instance.getServer().getPluginManager().disablePlugin(instance); instance.getServer().getPluginManager().disablePlugin(instance);
} }
e.printStackTrace();
} }
} }
@VisibleForTesting
public FlatFile(File source) {
this.source = source;
}
@Override
public void reload() {
throw new UnsupportedOperationException("Flatfile no longer supported");
}
@Override @Override
public synchronized boolean isAuthAvailable(String user) { public synchronized boolean isAuthAvailable(String user) {
BufferedReader br = null; BufferedReader br = null;
@ -66,19 +79,11 @@ public class FlatFile implements DataSource {
return true; return true;
} }
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return false;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return false; return false;
} finally { } finally {
if (br != null) { silentClose(br);
try {
br.close();
} catch (IOException ignored) {
}
}
} }
return false; return false;
} }
@ -100,17 +105,12 @@ public class FlatFile implements DataSource {
BufferedWriter bw = null; BufferedWriter bw = null;
try { try {
bw = new BufferedWriter(new FileWriter(source, true)); bw = new BufferedWriter(new FileWriter(source, true));
bw.write(auth.getNickname() + ":" + auth.getPassword() + ":" + auth.getIp() + ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY() + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n"); bw.write(auth.getNickname() + ":" + auth.getPassword().getHash() + ":" + auth.getIp() + ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY() + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return false; return false;
} finally { } finally {
if (bw != null) { silentClose(bw);
try {
bw.close();
} catch (IOException ignored) {
}
}
} }
return true; return true;
} }
@ -121,6 +121,7 @@ public class FlatFile implements DataSource {
} }
@Override @Override
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file.
public boolean updatePassword(String user, HashedPassword password) { public boolean updatePassword(String user, HashedPassword password) {
user = user.toLowerCase(); user = user.toLowerCase();
if (!isAuthAvailable(user)) { if (!isAuthAvailable(user)) {
@ -134,45 +135,18 @@ public class FlatFile implements DataSource {
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
String[] args = line.split(":"); String[] args = line.split(":");
if (args[0].equals(user)) { if (args[0].equals(user)) {
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file. newAuth = buildAuthFromArray(args);
switch (args.length) { if (newAuth != null) {
case 4: { newAuth.setPassword(password);
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), 0, 0, 0, "world", "your@email.com", args[0]);
break;
}
case 7: {
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "world", "your@email.com", args[0]);
break;
}
case 8: {
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
break;
}
case 9: {
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
break;
}
default: {
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], 0, 0, 0, 0, "world", "your@email.com", args[0]);
break;
}
} }
break; break;
} }
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return false;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return false; return false;
} finally { } finally {
if (br != null) { silentClose(br);
try {
br.close();
} catch (IOException ignored) {
}
}
} }
if (newAuth != null) { if (newAuth != null) {
removeAuth(user); removeAuth(user);
@ -194,44 +168,19 @@ public class FlatFile implements DataSource {
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
String[] args = line.split(":"); String[] args = line.split(":");
if (args[0].equalsIgnoreCase(auth.getNickname())) { if (args[0].equalsIgnoreCase(auth.getNickname())) {
switch (args.length) { newAuth = buildAuthFromArray(args);
case 4: { if (newAuth != null) {
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), 0, 0, 0, "world", "your@email.com", args[0]); newAuth.setLastLogin(auth.getLastLogin());
break; newAuth.setIp(auth.getIp());
}
case 7: {
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "world", "your@email.com", args[0]);
break;
}
case 8: {
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
break;
}
case 9: {
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
break;
}
default: {
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), 0, 0, 0, "world", "your@email.com", args[0]);
break;
}
} }
break; break;
} }
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return false;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return false; return false;
} finally { } finally {
if (br != null) { silentClose(br);
try {
br.close();
} catch (IOException ignored) {
}
}
} }
if (newAuth != null) { if (newAuth != null) {
removeAuth(auth.getNickname()); removeAuth(auth.getNickname());
@ -253,23 +202,22 @@ public class FlatFile implements DataSource {
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
String[] args = line.split(":"); String[] args = line.split(":");
if (args[0].equalsIgnoreCase(auth.getNickname())) { if (args[0].equalsIgnoreCase(auth.getNickname())) {
newAuth = new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ(), auth.getWorld(), auth.getEmail(), args[0]); newAuth = buildAuthFromArray(args);
if (newAuth != null) {
newAuth.setQuitLocX(auth.getQuitLocX());
newAuth.setQuitLocY(auth.getQuitLocY());
newAuth.setQuitLocZ(auth.getQuitLocZ());
newAuth.setWorld(auth.getWorld());
newAuth.setEmail(auth.getEmail());
}
break; break;
} }
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return false;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return false; return false;
} finally { } finally {
if (br != null) { silentClose(br);
try {
br.close();
} catch (IOException ignored) {
}
}
} }
if (newAuth != null) { if (newAuth != null) {
removeAuth(auth.getNickname()); removeAuth(auth.getNickname());
@ -301,25 +249,12 @@ public class FlatFile implements DataSource {
for (String l : lines) { for (String l : lines) {
bw.write(l + "\n"); bw.write(l + "\n");
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return cleared;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return cleared; return cleared;
} finally { } finally {
if (br != null) { silentClose(br);
try { silentClose(bw);
br.close();
} catch (IOException ignored) {
}
}
if (bw != null) {
try {
bw.close();
} catch (IOException ignored) {
}
}
} }
return cleared; return cleared;
} }
@ -345,25 +280,12 @@ public class FlatFile implements DataSource {
for (String l : lines) { for (String l : lines) {
bw.write(l + "\n"); bw.write(l + "\n");
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return false;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return false; return false;
} finally { } finally {
if (br != null) { silentClose(br);
try { silentClose(bw);
br.close();
} catch (IOException ignored) {
}
}
if (bw != null) {
try {
bw.close();
} catch (IOException ignored) {
}
}
} }
return true; return true;
} }
@ -377,35 +299,14 @@ public class FlatFile implements DataSource {
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
String[] args = line.split(":"); String[] args = line.split(":");
if (args[0].equalsIgnoreCase(user)) { if (args[0].equalsIgnoreCase(user)) {
switch (args.length) { return buildAuthFromArray(args);
case 2:
return new PlayerAuth(args[0], args[1], "192.168.0.1", 0, "your@email.com", args[0]);
case 3:
return new PlayerAuth(args[0], args[1], args[2], 0, "your@email.com", args[0]);
case 4:
return new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), "your@email.com", args[0]);
case 7:
return new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "unavailableworld", "your@email.com", args[0]);
case 8:
return new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
case 9:
return new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
}
} }
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return null;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return null; return null;
} finally { } finally {
if (br != null) { silentClose(br);
try {
br.close();
} catch (IOException ignored) {
}
}
} }
return null; return null;
} }
@ -414,10 +315,6 @@ public class FlatFile implements DataSource {
public synchronized void close() { public synchronized void close() {
} }
@Override
public void reload() {
}
@Override @Override
public boolean updateEmail(PlayerAuth auth) { public boolean updateEmail(PlayerAuth auth) {
if (!isAuthAvailable(auth.getNickname())) { if (!isAuthAvailable(auth.getNickname())) {
@ -431,7 +328,10 @@ public class FlatFile implements DataSource {
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
String[] args = line.split(":"); String[] args = line.split(":");
if (args[0].equals(auth.getNickname())) { if (args[0].equals(auth.getNickname())) {
newAuth = new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], auth.getEmail(), args[0]); newAuth = buildAuthFromArray(args);
if (newAuth != null) {
newAuth.setEmail(auth.getEmail());
}
break; break;
} }
} }
@ -539,18 +439,8 @@ public class FlatFile implements DataSource {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
} finally { } finally {
if (br != null) { silentClose(br);
try { silentClose(bw);
br.close();
} catch (IOException ignored) {
}
}
if (bw != null) {
try {
bw.close();
} catch (IOException ignored) {
}
}
} }
} }
@ -589,19 +479,14 @@ public class FlatFile implements DataSource {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.showError(ex.getMessage());
return result; return result;
} finally { } finally {
if (br != null) { silentClose(br);
try {
br.close();
} catch (IOException ignored) {
}
}
} }
return result; return result;
} }
@Override @Override
public boolean updateRealName(String user, String realName) { public boolean updateRealName(String user, String realName) {
return false; throw new UnsupportedOperationException("Flat file no longer supported");
} }
@Override @Override
@ -618,51 +503,56 @@ public class FlatFile implements DataSource {
String line; String line;
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
String[] args = line.split(":"); String[] args = line.split(":");
switch (args.length) { PlayerAuth auth = buildAuthFromArray(args);
case 2: if (auth != null) {
auths.add(new PlayerAuth(args[0], args[1], "192.168.0.1", 0, "your@email.com", args[0])); auths.add(auth);
break;
case 3:
auths.add(new PlayerAuth(args[0], args[1], args[2], 0, "your@email.com", args[0]));
break;
case 4:
auths.add(new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), "your@email.com", args[0]));
break;
case 7:
auths.add(new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "unavailableworld", "your@email.com", args[0]));
break;
case 8:
auths.add(new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]));
break;
case 9:
auths.add(new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]));
break;
} }
} }
} catch (FileNotFoundException ex) {
ConsoleLogger.showError(ex.getMessage());
return auths;
} catch (IOException ex) { } catch (IOException ex) {
ConsoleLogger.showError(ex.getMessage()); ConsoleLogger.logException("Error while getting auths from flatfile:", ex);
return auths;
} finally { } finally {
if (br != null) { silentClose(br);
try {
br.close();
} catch (IOException ignored) {
}
}
} }
return auths; return auths;
} }
@Override @Override
public List<PlayerAuth> getLoggedPlayers() { public List<PlayerAuth> getLoggedPlayers() {
return new ArrayList<>(); throw new UnsupportedOperationException("Flat file no longer supported");
} }
@Override @Override
public boolean isEmailStored(String email) { public boolean isEmailStored(String email) {
throw new UnsupportedOperationException("Flat file no longer supported"); throw new UnsupportedOperationException("Flat file no longer supported");
} }
private static PlayerAuth buildAuthFromArray(String[] args) {
// Format allows 2, 3, 4, 7, 8, 9 fields. Anything else is unknown
if (args.length >= 2 && args.length <= 9 && args.length != 5 && args.length != 6) {
PlayerAuth.Builder builder = PlayerAuth.builder()
.name(args[0]).realName(args[0]).password(args[1], null);
if (args.length >= 3) builder.ip(args[2]);
if (args.length >= 4) builder.lastLogin(Long.parseLong(args[3]));
if (args.length >= 7) {
builder.locX(Double.parseDouble(args[4]))
.locY(Double.parseDouble(args[5]))
.locZ(Double.parseDouble(args[6]));
}
if (args.length >= 8) builder.locWorld(args[7]);
if (args.length >= 9) builder.email(args[8]);
return builder.build();
}
return null;
}
private static void silentClose(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ignored) {
// silent close
}
}
}
} }

View File

@ -3,7 +3,6 @@ package fr.xephi.authme.datasource;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException; import com.zaxxer.hikari.pool.HikariPool.PoolInitializationException;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.security.HashAlgorithm;
@ -42,6 +41,10 @@ public class MySQL implements DataSource {
private final HashAlgorithm hashAlgorithm; private final HashAlgorithm hashAlgorithm;
private HikariDataSource ds; private HikariDataSource ds;
private final String phpBbPrefix;
private final int phpBbGroup;
private final String wordpressPrefix;
public MySQL(NewSetting settings) throws ClassNotFoundException, SQLException, PoolInitializationException { public MySQL(NewSetting settings) throws ClassNotFoundException, SQLException, PoolInitializationException {
this.host = settings.getProperty(DatabaseSettings.MYSQL_HOST); this.host = settings.getProperty(DatabaseSettings.MYSQL_HOST);
this.port = settings.getProperty(DatabaseSettings.MYSQL_PORT); this.port = settings.getProperty(DatabaseSettings.MYSQL_PORT);
@ -52,6 +55,9 @@ public class MySQL implements DataSource {
this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS); this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS);
this.col = new Columns(settings); this.col = new Columns(settings);
this.hashAlgorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH); this.hashAlgorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.phpBbPrefix = settings.getProperty(HooksSettings.PHPBB_TABLE_PREFIX);
this.phpBbGroup = settings.getProperty(HooksSettings.PHPBB_ACTIVATED_GROUP_ID);
this.wordpressPrefix = settings.getProperty(HooksSettings.WORDPRESS_TABLE_PREFIX);
// Set the connection arguments (and check if connection is ok) // Set the connection arguments (and check if connection is ok)
try { try {
@ -93,6 +99,9 @@ public class MySQL implements DataSource {
this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS); this.columnOthers = settings.getProperty(HooksSettings.MYSQL_OTHER_USERNAME_COLS);
this.col = new Columns(settings); this.col = new Columns(settings);
this.hashAlgorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH); this.hashAlgorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.phpBbPrefix = settings.getProperty(HooksSettings.PHPBB_TABLE_PREFIX);
this.phpBbGroup = settings.getProperty(HooksSettings.PHPBB_ACTIVATED_GROUP_ID);
this.wordpressPrefix = settings.getProperty(HooksSettings.WORDPRESS_TABLE_PREFIX);
ds = hikariDataSource; ds = hikariDataSource;
} }
@ -122,7 +131,8 @@ public class MySQL implements DataSource {
ConsoleLogger.info("Connection arguments loaded, Hikari ConnectionPool ready!"); ConsoleLogger.info("Connection arguments loaded, Hikari ConnectionPool ready!");
} }
private synchronized void reloadArguments() throws RuntimeException { @Override
public synchronized void reload() throws RuntimeException {
if (ds != null) { if (ds != null) {
ds.close(); ds.close();
} }
@ -361,10 +371,10 @@ public class MySQL implements DataSource {
if (rs.next()) { if (rs.next()) {
int id = rs.getInt(col.ID); int id = rs.getInt(col.ID);
// Insert player in phpbb_user_group // Insert player in phpbb_user_group
sql = "INSERT INTO " + Settings.getPhpbbPrefix sql = "INSERT INTO " + phpBbPrefix
+ "user_group (group_id, user_id, group_leader, user_pending) VALUES (?,?,?,?);"; + "user_group (group_id, user_id, group_leader, user_pending) VALUES (?,?,?,?);";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
pst2.setInt(1, Settings.getPhpbbGroup); pst2.setInt(1, phpBbGroup);
pst2.setInt(2, id); pst2.setInt(2, id);
pst2.setInt(3, 0); pst2.setInt(3, 0);
pst2.setInt(4, 0); pst2.setInt(4, 0);
@ -382,7 +392,7 @@ public class MySQL implements DataSource {
sql = "UPDATE " + tableName + " SET " + tableName sql = "UPDATE " + tableName + " SET " + tableName
+ ".group_id=? WHERE " + col.NAME + "=?;"; + ".group_id=? WHERE " + col.NAME + "=?;";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
pst2.setInt(1, Settings.getPhpbbGroup); pst2.setInt(1, phpBbGroup);
pst2.setString(2, auth.getNickname()); pst2.setString(2, auth.getNickname());
pst2.executeUpdate(); pst2.executeUpdate();
pst2.close(); pst2.close();
@ -405,7 +415,7 @@ public class MySQL implements DataSource {
pst2.executeUpdate(); pst2.executeUpdate();
pst2.close(); pst2.close();
// Increment num_users // Increment num_users
sql = "UPDATE " + Settings.getPhpbbPrefix sql = "UPDATE " + phpBbPrefix
+ "config SET config_value = config_value + 1 WHERE config_name = 'num_users';"; + "config SET config_value = config_value + 1 WHERE config_name = 'num_users';";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
pst2.executeUpdate(); pst2.executeUpdate();
@ -419,7 +429,7 @@ public class MySQL implements DataSource {
rs = pst.executeQuery(); rs = pst.executeQuery();
if (rs.next()) { if (rs.next()) {
int id = rs.getInt(col.ID); int id = rs.getInt(col.ID);
sql = "INSERT INTO " + Settings.getWordPressPrefix + "usermeta (user_id, meta_key, meta_value) VALUES (?,?,?);"; sql = "INSERT INTO " + wordpressPrefix + "usermeta (user_id, meta_key, meta_value) VALUES (?,?,?);";
pst2 = con.prepareStatement(sql); pst2 = con.prepareStatement(sql);
// First Name // First Name
pst2.setInt(1, id); pst2.setInt(1, id);
@ -622,31 +632,32 @@ public class MySQL implements DataSource {
@Override @Override
public synchronized boolean removeAuth(String user) { public synchronized boolean removeAuth(String user) {
user = user.toLowerCase(); user = user.toLowerCase();
try (Connection con = getConnection()) { String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
String sql; PreparedStatement xfSelect = null;
PreparedStatement pst; PreparedStatement xfDelete = null;
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
if (hashAlgorithm == HashAlgorithm.XFBCRYPT) { if (hashAlgorithm == HashAlgorithm.XFBCRYPT) {
sql = "SELECT " + col.ID + " FROM " + tableName + " WHERE " + col.NAME + "=?;"; sql = "SELECT " + col.ID + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
pst = con.prepareStatement(sql); xfSelect = con.prepareStatement(sql);
pst.setString(1, user); xfSelect.setString(1, user);
ResultSet rs = pst.executeQuery(); try (ResultSet rs = xfSelect.executeQuery()) {
if (rs.next()) { if (rs.next()) {
int id = rs.getInt(col.ID); int id = rs.getInt(col.ID);
sql = "DELETE FROM xf_user_authenticate WHERE " + col.ID + "=?;"; sql = "DELETE FROM xf_user_authenticate WHERE " + col.ID + "=?;";
PreparedStatement st = con.prepareStatement(sql); xfDelete = con.prepareStatement(sql);
st.setInt(1, id); xfDelete.setInt(1, id);
st.executeUpdate(); xfDelete.executeUpdate();
st.close(); }
} }
rs.close();
pst.close();
} }
pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;");
pst.setString(1, user); pst.setString(1, user);
pst.executeUpdate(); pst.executeUpdate();
return true; return true;
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(xfSelect);
close(xfDelete);
} }
return false; return false;
} }
@ -684,17 +695,6 @@ public class MySQL implements DataSource {
return false; return false;
} }
@Override
public void reload() {
try {
reloadArguments();
} catch (Exception ex) {
ConsoleLogger.logException("Can't reconnect to MySQL database... " +
"Please check your MySQL configuration! Encountered", ex);
AuthMe.getInstance().stopOrUnload();
}
}
@Override @Override
public synchronized void close() { public synchronized void close() {
if (ds != null && !ds.isClosed()) { if (ds != null && !ds.isClosed()) {
@ -881,22 +881,24 @@ public class MySQL implements DataSource {
@Override @Override
public List<PlayerAuth> getLoggedPlayers() { public List<PlayerAuth> getLoggedPlayers() {
List<PlayerAuth> auths = new ArrayList<>(); List<PlayerAuth> auths = new ArrayList<>();
try (Connection con = getConnection()) { String sql = "SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;";
Statement st = con.createStatement(); try (Connection con = getConnection();
ResultSet rs = st.executeQuery("SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;"); Statement st = con.createStatement();
PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + col.ID + "=?;"); ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) { while (rs.next()) {
PlayerAuth pAuth = buildAuthFromResultSet(rs); PlayerAuth pAuth = buildAuthFromResultSet(rs);
if (hashAlgorithm == HashAlgorithm.XFBCRYPT) { if (hashAlgorithm == HashAlgorithm.XFBCRYPT) {
int id = rs.getInt(col.ID); try (PreparedStatement pst = con.prepareStatement("SELECT data FROM xf_user_authenticate WHERE " + col.ID + "=?;")) {
pst.setInt(1, id); int id = rs.getInt(col.ID);
ResultSet rs2 = pst.executeQuery(); pst.setInt(1, id);
if (rs2.next()) { ResultSet rs2 = pst.executeQuery();
Blob blob = rs2.getBlob("data"); if (rs2.next()) {
byte[] bytes = blob.getBytes(1, (int) blob.length()); Blob blob = rs2.getBlob("data");
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes))); byte[] bytes = blob.getBytes(1, (int) blob.length());
pAuth.setPassword(new HashedPassword(XFBCRYPT.getHashFromBlob(bytes)));
}
rs2.close();
} }
rs2.close();
} }
auths.add(pAuth); auths.add(pAuth);
} }
@ -980,12 +982,22 @@ public class MySQL implements DataSource {
} }
private static void close(ResultSet rs) { private static void close(ResultSet rs) {
if (rs != null) { try {
try { if (rs != null && !rs.isClosed()) {
rs.close(); rs.close();
} catch (SQLException e) {
ConsoleLogger.logException("Could not close ResultSet", e);
} }
} catch (SQLException e) {
ConsoleLogger.logException("Could not close ResultSet", e);
}
}
private static void close(PreparedStatement pst) {
try {
if (pst != null && !pst.isClosed()) {
pst.close();
}
} catch (SQLException e) {
ConsoleLogger.logException("Could not close PreparedStatement", e);
} }
} }

View File

@ -30,8 +30,10 @@ public class SQLite implements DataSource {
/** /**
* Constructor for SQLite. * Constructor for SQLite.
* *
* @throws ClassNotFoundException Exception * @param settings The settings instance
* @throws SQLException Exception *
* @throws ClassNotFoundException if no driver could be found for the datasource
* @throws SQLException when initialization of a SQL datasource failed
*/ */
public SQLite(NewSetting settings) throws ClassNotFoundException, SQLException { public SQLite(NewSetting settings) throws ClassNotFoundException, SQLException {
this.database = settings.getProperty(DatabaseSettings.MYSQL_DATABASE); this.database = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
@ -55,6 +57,10 @@ public class SQLite implements DataSource {
this.con = connection; this.con = connection;
} }
private static void logSqlException(SQLException e) {
ConsoleLogger.logException("Error while executing SQL statement:", e);
}
private synchronized void connect() throws ClassNotFoundException, SQLException { private synchronized void connect() throws ClassNotFoundException, SQLException {
Class.forName("org.sqlite.JDBC"); Class.forName("org.sqlite.JDBC");
ConsoleLogger.info("SQLite driver loaded"); ConsoleLogger.info("SQLite driver loaded");
@ -123,6 +129,11 @@ public class SQLite implements DataSource {
ConsoleLogger.info("SQLite Setup finished"); ConsoleLogger.info("SQLite Setup finished");
} }
@Override
public void reload() {
// TODO 20160309: Implement reloading
}
@Override @Override
public synchronized boolean isAuthAvailable(String user) { public synchronized boolean isAuthAvailable(String user) {
PreparedStatement pst = null; PreparedStatement pst = null;
@ -277,24 +288,23 @@ public class SQLite implements DataSource {
@Override @Override
public List<String> autoPurgeDatabase(long until) { public List<String> autoPurgeDatabase(long until) {
PreparedStatement pst = null;
ResultSet rs = null;
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
try { String select = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.LAST_LOGIN + "<?;";
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + col.LAST_LOGIN + "<?;"); String delete = "DELETE FROM " + tableName + " WHERE " + col.LAST_LOGIN + "<?;";
pst.setLong(1, until); try (PreparedStatement selectPst = con.prepareStatement(select);
rs = pst.executeQuery(); PreparedStatement deletePst = con.prepareStatement(delete)) {
while (rs.next()) { selectPst.setLong(1, until);
list.add(rs.getString(col.NAME)); try (ResultSet rs = selectPst.executeQuery()) {
while (rs.next()) {
list.add(rs.getString(col.NAME));
}
} }
return list; deletePst.setLong(1, until);
deletePst.executeUpdate();
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(rs);
close(pst);
} }
return new ArrayList<>(); return list;
} }
@Override @Override
@ -350,17 +360,14 @@ public class SQLite implements DataSource {
@Override @Override
public synchronized void close() { public synchronized void close() {
try { try {
if (con != null && !con.isClosed()) if (con != null && !con.isClosed()) {
con.close(); con.close();
}
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} }
} }
@Override
public void reload() {
}
private void close(Statement st) { private void close(Statement st) {
if (st != null) { if (st != null) {
try { try {
@ -421,17 +428,14 @@ public class SQLite implements DataSource {
@Override @Override
public void purgeBanned(List<String> banned) { public void purgeBanned(List<String> banned) {
PreparedStatement pst = null; String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
try { try (PreparedStatement pst = con.prepareStatement(sql)) {
for (String name : banned) { for (String name : banned) {
pst = con.prepareStatement("DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;");
pst.setString(1, name); pst.setString(1, name);
pst.executeUpdate(); pst.executeUpdate();
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
} }
@ -507,18 +511,13 @@ public class SQLite implements DataSource {
@Override @Override
public int getAccountsRegistered() { public int getAccountsRegistered() {
PreparedStatement pst = null; String sql = "SELECT COUNT(*) FROM " + tableName + ";";
ResultSet rs; try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
try { if (rs.next()) {
pst = con.prepareStatement("SELECT COUNT(*) FROM " + tableName + ";");
rs = pst.executeQuery();
if (rs != null && rs.next()) {
return rs.getInt(1); return rs.getInt(1);
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
return 0; return 0;
} }
@ -526,7 +525,7 @@ public class SQLite implements DataSource {
@Override @Override
public boolean updateRealName(String user, String realName) { public boolean updateRealName(String user, String realName) {
String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; String sql = "UPDATE " + tableName + " SET " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;";
try(PreparedStatement pst = con.prepareStatement(sql)) { try (PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, realName); pst.setString(1, realName);
pst.setString(2, user); pst.setString(2, user);
pst.executeUpdate(); pst.executeUpdate();
@ -540,7 +539,7 @@ public class SQLite implements DataSource {
@Override @Override
public boolean updateIp(String user, String ip) { public boolean updateIp(String user, String ip) {
String sql = "UPDATE " + tableName + " SET " + col.IP + "=? WHERE " + col.NAME + "=?;"; String sql = "UPDATE " + tableName + " SET " + col.IP + "=? WHERE " + col.NAME + "=?;";
try(PreparedStatement pst = con.prepareStatement(sql)) { try (PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, ip); pst.setString(1, ip);
pst.setString(2, user); pst.setString(2, user);
pst.executeUpdate(); pst.executeUpdate();
@ -554,19 +553,14 @@ public class SQLite implements DataSource {
@Override @Override
public List<PlayerAuth> getAllAuths() { public List<PlayerAuth> getAllAuths() {
List<PlayerAuth> auths = new ArrayList<>(); List<PlayerAuth> auths = new ArrayList<>();
PreparedStatement pst = null; String sql = "SELECT * FROM " + tableName + ";";
ResultSet rs; try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
try {
pst = con.prepareStatement("SELECT * FROM " + tableName + ";");
rs = pst.executeQuery();
while (rs.next()) { while (rs.next()) {
PlayerAuth auth = buildAuthFromResultSet(rs); PlayerAuth auth = buildAuthFromResultSet(rs);
auths.add(auth); auths.add(auth);
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
return auths; return auths;
} }
@ -574,19 +568,14 @@ public class SQLite implements DataSource {
@Override @Override
public List<PlayerAuth> getLoggedPlayers() { public List<PlayerAuth> getLoggedPlayers() {
List<PlayerAuth> auths = new ArrayList<>(); List<PlayerAuth> auths = new ArrayList<>();
PreparedStatement pst = null; String sql = "SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;";
ResultSet rs; try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
try {
pst = con.prepareStatement("SELECT * FROM " + tableName + " WHERE " + col.IS_LOGGED + "=1;");
rs = pst.executeQuery();
while (rs.next()) { while (rs.next()) {
PlayerAuth auth = buildAuthFromResultSet(rs); PlayerAuth auth = buildAuthFromResultSet(rs);
auths.add(auth); auths.add(auth);
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
return auths; return auths;
} }
@ -607,10 +596,6 @@ public class SQLite implements DataSource {
return false; return false;
} }
private static void logSqlException(SQLException e) {
ConsoleLogger.logException("Error while executing SQL statement:", e);
}
private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException { private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException {
String salt = !col.SALT.isEmpty() ? row.getString(col.SALT) : null; String salt = !col.SALT.isEmpty() ? row.getString(col.SALT) : null;

View File

@ -6,7 +6,7 @@ import org.bukkit.event.HandlerList;
/** /**
* This event is called when a player uses the /login command with correct credentials. * This event is called when a player uses the /login command with correct credentials.
* {@link #setCanLogin(boolean) {@code event.setCanLogin(false)}} prevents the player from logging in. * {@link #setCanLogin(boolean) event.setCanLogin(false)} prevents the player from logging in.
*/ */
public class AuthMeAsyncPreLoginEvent extends CustomEvent { public class AuthMeAsyncPreLoginEvent extends CustomEvent {

View File

@ -7,6 +7,7 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.messaging.PluginMessageListener; import org.bukkit.plugin.messaging.PluginMessageListener;
@ -15,30 +16,33 @@ import org.bukkit.plugin.messaging.PluginMessageListener;
*/ */
public class BungeeCordMessage implements PluginMessageListener { public class BungeeCordMessage implements PluginMessageListener {
public final AuthMe plugin; private final AuthMe plugin;
private final IpAddressManager ipAddressManager;
/** /**
* Constructor for BungeeCordMessage. * Constructor for BungeeCordMessage.
* *
* @param plugin AuthMe * @param plugin The plugin instance
* @param ipAddressManager The IP address manager
*/ */
public BungeeCordMessage(AuthMe plugin) { public BungeeCordMessage(AuthMe plugin, IpAddressManager ipAddressManager) {
this.plugin = plugin; this.plugin = plugin;
this.ipAddressManager = ipAddressManager;
} }
@Override @Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) { public void onPluginMessageReceived(String channel, Player player, byte[] message) {
if (!channel.equals("BungeeCord")) { if (!"BungeeCord".equals(channel)) {
return; return;
} }
ByteArrayDataInput in = ByteStreams.newDataInput(message); ByteArrayDataInput in = ByteStreams.newDataInput(message);
String subChannel = in.readUTF(); String subChannel = in.readUTF();
if (subChannel.equals("IP")) { // We need only the IP channel if ("IP".equals(subChannel)) { // We need only the IP channel
String ip = in.readUTF(); String ip = in.readUTF();
// Put the IP (only the ip not the port) in the hashMap // Put the IP (only the ip not the port) in the hashMap
plugin.realIp.put(player.getName().toLowerCase(), ip); ipAddressManager.addCache(player.getName(), ip);
} }
if (subChannel.equalsIgnoreCase("AuthMe")) { if ("AuthMe".equalsIgnoreCase(subChannel)) {
String str = in.readUTF(); String str = in.readUTF();
final String[] args = str.split(";"); final String[] args = str.split(";");
final String act = args[0]; final String act = args[0];
@ -65,10 +69,10 @@ public class BungeeCordMessage implements PluginMessageListener {
ConsoleLogger.info("Player " + auth.getNickname() ConsoleLogger.info("Player " + auth.getNickname()
+ " has registered out from one of your server!"); + " has registered out from one of your server!");
} else if ("changepassword".equals(act)) { } else if ("changepassword".equals(act)) {
final String password = args[2]; final String password = args[2];
final String salt = args.length >= 4 ? args[3] : null; final String salt = args.length >= 4 ? args[3] : null;
auth.setPassword(new HashedPassword(password, salt)); auth.setPassword(new HashedPassword(password, salt));
PlayerCache.getInstance().updatePlayer(auth); PlayerCache.getInstance().updatePlayer(auth);
dataSource.updatePassword(auth); dataSource.updatePassword(auth);
} }

View File

@ -1,51 +0,0 @@
package fr.xephi.authme.hooks;
import fr.xephi.authme.settings.CustomConfiguration;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import java.io.File;
/**
*/
public class EssSpawn extends CustomConfiguration {
private static EssSpawn spawn;
public EssSpawn() {
super(new File("." + File.separator + "plugins" + File.separator + "Essentials" + File.separator + "spawn.yml"));
spawn = this;
load();
}
/**
* Method getInstance.
*
* @return EssSpawn
*/
public static EssSpawn getInstance() {
if (spawn == null) {
spawn = new EssSpawn();
}
return spawn;
}
/**
* Method getLocation.
*
* @return Location
*/
public Location getLocation() {
try {
if (!this.contains("spawns.default.world"))
return null;
if (this.getString("spawns.default.world").isEmpty() || this.getString("spawns.default.world").equals(""))
return null;
Location location = new Location(Bukkit.getWorld(this.getString("spawns.default.world")), this.getDouble("spawns.default.x"), this.getDouble("spawns.default.y"), this.getDouble("spawns.default.z"), Float.parseFloat(this.getString("spawns.default.yaw")), Float.parseFloat(this.getString("spawns.default.pitch")));
return location;
} catch (NullPointerException | NumberFormatException npe) {
return null;
}
}
}

View File

@ -0,0 +1,158 @@
package fr.xephi.authme.hooks;
import com.earth2me.essentials.Essentials;
import com.onarandombox.MultiverseCore.MultiverseCore;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import fr.xephi.authme.ConsoleLogger;
import net.minelink.ctplus.CombatTagPlus;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import java.io.File;
/**
* Hooks into third-party plugins and allows to perform actions on them.
*/
public class PluginHooks {
private final PluginManager pluginManager;
private Essentials essentials;
private MultiverseCore multiverse;
private CombatTagPlus combatTagPlus;
/**
* Constructor.
*
* @param pluginManager The server's plugin manager
*/
public PluginHooks(PluginManager pluginManager) {
this.pluginManager = pluginManager;
tryHookToCombatPlus();
tryHookToEssentials();
tryHookToMultiverse();
}
/**
* Enable or disable the social spy status of the given user if Essentials is available.
*
* @param player The player to modify
* @param socialSpyStatus The social spy status (enabled/disabled) to set
*/
public void setEssentialsSocialSpyStatus(Player player, boolean socialSpyStatus) {
if (essentials != null) {
essentials.getUser(player).setSocialSpyEnabled(socialSpyStatus);
}
}
/**
* If Essentials is hooked into, return Essentials' data folder.
*
* @return The Essentials data folder, or null if unavailable
*/
public File getEssentialsDataFolder() {
if (essentials != null) {
return essentials.getDataFolder();
}
return null;
}
/**
* Return the spawn of the given world as defined by Multiverse (if available).
*
* @param world The world to get the Multiverse spawn for
* @return The spawn location from Multiverse, or null if unavailable
*/
public Location getMultiverseSpawn(World world) {
if (multiverse != null) {
MVWorldManager manager = multiverse.getMVWorldManager();
if (manager.isMVWorld(world)) {
return manager.getMVWorld(world).getSpawnLocation();
}
}
return null;
}
/**
* Query the CombatTagPlus plugin whether the given player is an NPC.
*
* @param player The player to verify
* @return True if the player is an NPC according to CombatTagPlus, false if not or if the plugin is unavailable
*/
public boolean isNpcInCombatTagPlus(Player player) {
return combatTagPlus != null && combatTagPlus.getNpcPlayerHelper().isNpc(player);
}
// ------
// "Is plugin available" methods
// ------
public boolean isEssentialsAvailable() {
return essentials != null;
}
public boolean isMultiverseAvailable() {
return multiverse != null;
}
public boolean isCombatTagPlusAvailable() {
return combatTagPlus != null;
}
// ------
// Hook methods
// ------
public void tryHookToEssentials() {
try {
essentials = getPlugin(pluginManager, "Essentials", Essentials.class);
} catch (Exception | NoClassDefFoundError ignored) {
essentials = null;
}
}
public void tryHookToCombatPlus() {
try {
combatTagPlus = getPlugin(pluginManager, "CombatTagPlus", CombatTagPlus.class);
} catch (Exception | NoClassDefFoundError ignored) {
combatTagPlus = null;
}
}
public void tryHookToMultiverse() {
try {
multiverse = getPlugin(pluginManager, "Multiverse-Core", MultiverseCore.class);
} catch (Exception | NoClassDefFoundError ignored) {
multiverse = null;
}
}
// ------
// Unhook methods
// ------
public void unhookEssentials() {
essentials = null;
}
public void unhookCombatPlus() {
combatTagPlus = null;
}
public void unhookMultiverse() {
multiverse = null;
}
// ------
// Helpers
// ------
private static <T extends Plugin> T getPlugin(PluginManager pluginManager, String name, Class<T> clazz)
throws Exception, NoClassDefFoundError {
if (pluginManager.isPluginEnabled(name)) {
T plugin = clazz.cast(pluginManager.getPlugin(name));
ConsoleLogger.info("Hooked successfully into " + name);
return plugin;
}
return null;
}
}

View File

@ -87,7 +87,7 @@ public class AuthMeEntityListener implements Listener {
} }
} }
// TODO: Need to check this, player can't throw snowball but the item is taken. // TODO #568: Need to check this, player can't throw snowball but the item is taken.
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onProjectileLaunch(ProjectileLaunchEvent event) { public void onProjectileLaunch(ProjectileLaunchEvent event) {
if (event.getEntity() == null) { if (event.getEntity() == null) {
@ -103,7 +103,7 @@ public class AuthMeEntityListener implements Listener {
} }
player = (Player) shooter; player = (Player) shooter;
} else { } else {
// TODO ljacqu 20151220: Invoking getShooter() with null but method isn't static // TODO #568 20151220: Invoking getShooter() with null but method isn't static
try { try {
if (getShooter == null) { if (getShooter == null) {
getShooter = Projectile.class.getMethod("getShooter"); getShooter = Projectile.class.getMethod("getShooter");

View File

@ -22,29 +22,35 @@ import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.MethodUtils;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.logging.Level; import java.util.logging.Level;
/** import org.bukkit.Material;
*/ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
public class AuthMeInventoryPacketAdapter extends PacketAdapter { public class AuthMeInventoryPacketAdapter extends PacketAdapter {
private static final int PLAYER_INVENTORY = 0; private static final int PLAYER_INVENTORY = 0;
// http://wiki.vg/Inventory#Inventory (0-4 crafting, 5-8 armor, 9-35 main inventory, 36-44 hotbar) // http://wiki.vg/Inventory#Inventory (0-4 crafting, 5-8 armor, 9-35 main inventory, 36-44 hotbar, 45 off hand)
// +1 because an index starts with 0 // +1 because an index starts with 0
private static final int CRAFTING_SIZE = 5; private static final int CRAFTING_SIZE = 5;
private static final int ARMOR_SIZE = 4; private static final int ARMOR_SIZE = 4;
private static final int MAIN_SIZE = 27; private static final int MAIN_SIZE = 27;
private static final int HOTBAR_SIZE = 9; private static final int HOTBAR_SIZE = 9;
private static final int OFF_HAND_POSITION = 45;
private final boolean offHandSupported = MethodUtils
.getAccessibleMethod(PlayerInventory.class, "getItemInOffHand", new Class[]{}) != null;
public AuthMeInventoryPacketAdapter(AuthMe plugin) { public AuthMeInventoryPacketAdapter(AuthMe plugin) {
super(plugin, PacketType.Play.Server.SET_SLOT, PacketType.Play.Server.WINDOW_ITEMS); super(plugin, PacketType.Play.Server.SET_SLOT, PacketType.Play.Server.WINDOW_ITEMS);
@ -90,17 +96,23 @@ public class AuthMeInventoryPacketAdapter extends PacketAdapter {
ItemStack[] storedInventory = Arrays.copyOfRange(mainInventory, HOTBAR_SIZE, mainInventory.length); ItemStack[] storedInventory = Arrays.copyOfRange(mainInventory, HOTBAR_SIZE, mainInventory.length);
// concat all parts of the inventory together // concat all parts of the inventory together
int inventorySize = playerCrafting.length + armorContents.length + mainInventory.length; int inventorySize = CRAFTING_SIZE + ARMOR_SIZE + MAIN_SIZE + HOTBAR_SIZE;
if (offHandSupported) {
inventorySize++;
}
ItemStack[] completeInventory = new ItemStack[inventorySize]; ItemStack[] completeInventory = new ItemStack[inventorySize];
System.arraycopy(playerCrafting, 0, completeInventory, 0, playerCrafting.length); System.arraycopy(playerCrafting, 0, completeInventory, 0, CRAFTING_SIZE);
System.arraycopy(armorContents, 0, completeInventory, playerCrafting.length, armorContents.length); System.arraycopy(armorContents, 0, completeInventory, CRAFTING_SIZE, ARMOR_SIZE);
// storedInventory and hotbar // storedInventory and hotbar
System.arraycopy(storedInventory, 0, completeInventory System.arraycopy(storedInventory, 0, completeInventory, CRAFTING_SIZE + ARMOR_SIZE, MAIN_SIZE);
, playerCrafting.length + armorContents.length, storedInventory.length); System.arraycopy(hotbar, 0, completeInventory, CRAFTING_SIZE + ARMOR_SIZE + MAIN_SIZE, HOTBAR_SIZE);
System.arraycopy(hotbar, 0, completeInventory
, playerCrafting.length + armorContents.length + storedInventory.length, hotbar.length); if (offHandSupported) {
completeInventory[OFF_HAND_POSITION] = player.getInventory().getItemInOffHand();
}
inventoryPacket.getItemArrayModifier().write(0, completeInventory); inventoryPacket.getItemArrayModifier().write(0, completeInventory);
try { try {

View File

@ -9,10 +9,12 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer; import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.GeoLiteAPI; import fr.xephi.authme.util.GeoLiteAPI;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
@ -58,10 +60,17 @@ public class AuthMePlayerListener implements Listener {
public static final ConcurrentHashMap<String, Boolean> causeByAuthMe = new ConcurrentHashMap<>(); public static final ConcurrentHashMap<String, Boolean> causeByAuthMe = new ConcurrentHashMap<>();
private final AuthMe plugin; private final AuthMe plugin;
private final Messages m; private final Messages m;
private final DataSource dataSource;
private final AntiBot antiBot;
private final Management management;
public AuthMePlayerListener(AuthMe plugin) { public AuthMePlayerListener(AuthMe plugin, Messages messages, DataSource dataSource, AntiBot antiBot,
this.m = plugin.getMessages(); Management management) {
this.plugin = plugin; this.plugin = plugin;
this.m = messages;
this.dataSource = dataSource;
this.antiBot = antiBot;
this.management = management;
} }
private void handleChat(AsyncPlayerChatEvent event) { private void handleChat(AsyncPlayerChatEvent event) {
@ -80,15 +89,14 @@ public class AuthMePlayerListener implements Listener {
} }
event.setCancelled(true); event.setCancelled(true);
sendLoginRegisterMSG(player); sendLoginOrRegisterMessage(player);
} }
// TODO: new name private void sendLoginOrRegisterMessage(final Player player) {
private void sendLoginRegisterMSG(final Player player) {
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() { plugin.getServer().getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {
if (plugin.getDataSource().isAuthAvailable(player.getName().toLowerCase())) { if (dataSource.isAuthAvailable(player.getName().toLowerCase())) {
m.send(player, MessageKey.LOGIN_MESSAGE); m.send(player, MessageKey.LOGIN_MESSAGE);
} else { } else {
if (Settings.emailRegistration) { if (Settings.emailRegistration) {
@ -117,7 +125,7 @@ public class AuthMePlayerListener implements Listener {
return; return;
} }
event.setCancelled(true); event.setCancelled(true);
sendLoginRegisterMSG(event.getPlayer()); sendLoginOrRegisterMessage(event.getPlayer());
} }
@EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL) @EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL)
@ -230,14 +238,14 @@ public class AuthMePlayerListener implements Listener {
Bukkit.getScheduler().runTask(plugin, new Runnable() { Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {
plugin.getManagement().performJoin(player); management.performJoin(player);
} }
}); });
} }
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onPreLogin(AsyncPlayerPreLoginEvent event) { public void onPreLogin(AsyncPlayerPreLoginEvent event) {
PlayerAuth auth = plugin.getDataSource().getAuth(event.getName()); PlayerAuth auth = dataSource.getAuth(event.getName());
if (Settings.preventOtherCase && auth != null && auth.getRealName() != null) { if (Settings.preventOtherCase && auth != null && auth.getRealName() != null) {
String realName = auth.getRealName(); String realName = auth.getRealName();
if (!realName.isEmpty() && !realName.equals("Player") && !realName.equals(event.getName())) { if (!realName.isEmpty() && !realName.equals("Player") && !realName.equals(event.getName())) {
@ -246,7 +254,7 @@ public class AuthMePlayerListener implements Listener {
return; return;
} }
if (realName.isEmpty() || realName.equals("Player")) { if (realName.isEmpty() || realName.equals("Player")) {
plugin.getDataSource().updateRealName(event.getName().toLowerCase(), event.getName()); dataSource.updateRealName(event.getName().toLowerCase(), event.getName());
} }
} }
@ -320,7 +328,7 @@ public class AuthMePlayerListener implements Listener {
} }
final String name = player.getName().toLowerCase(); final String name = player.getName().toLowerCase();
boolean isAuthAvailable = plugin.getDataSource().isAuthAvailable(name); boolean isAuthAvailable = dataSource.isAuthAvailable(name);
if (Settings.isKickNonRegisteredEnabled && !isAuthAvailable) { if (Settings.isKickNonRegisteredEnabled && !isAuthAvailable) {
if (Settings.antiBotInAction) { if (Settings.antiBotInAction) {
@ -346,7 +354,7 @@ public class AuthMePlayerListener implements Listener {
return; return;
} }
AntiBot.checkAntiBot(player); antiBot.checkAntiBot(player);
if (Settings.bungee) { if (Settings.bungee) {
ByteArrayDataOutput out = ByteStreams.newDataOutput(); ByteArrayDataOutput out = ByteStreams.newDataOutput();
@ -367,7 +375,7 @@ public class AuthMePlayerListener implements Listener {
event.setQuitMessage(null); event.setQuitMessage(null);
} }
plugin.getManagement().performQuit(player, false); management.performQuit(player, false);
} }
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
@ -493,13 +501,13 @@ public class AuthMePlayerListener implements Listener {
Player player = event.getPlayer(); Player player = event.getPlayer();
String name = player.getName().toLowerCase(); String name = player.getName().toLowerCase();
Location spawn = plugin.getSpawnLocation(player); Location spawn = plugin.getSpawnLocation(player);
if (Settings.isSaveQuitLocationEnabled && plugin.getDataSource().isAuthAvailable(name)) { if (Settings.isSaveQuitLocationEnabled && dataSource.isAuthAvailable(name)) {
PlayerAuth auth = PlayerAuth.builder() PlayerAuth auth = PlayerAuth.builder()
.name(name) .name(name)
.realName(player.getName()) .realName(player.getName())
.location(spawn) .location(spawn)
.build(); .build();
plugin.getDataSource().updateQuitLoc(auth); dataSource.updateQuitLoc(auth);
} }
if (spawn != null && spawn.getWorld() != null) { if (spawn != null && spawn.getWorld() != null) {
event.setRespawnLocation(spawn); event.setRespawnLocation(spawn);

View File

@ -2,9 +2,11 @@ package fr.xephi.authme.listener;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.output.Messages;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.util.GeoLiteAPI; import fr.xephi.authme.util.GeoLiteAPI;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -12,18 +14,21 @@ import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent; import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent; import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.event.server.ServerListPingEvent;
import org.bukkit.plugin.Plugin;
/** /**
*/ */
public class AuthMeServerListener implements Listener { public class AuthMeServerListener implements Listener {
private final AuthMe plugin; private final AuthMe plugin;
private final Messages m; private final Messages messages;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
public AuthMeServerListener(AuthMe plugin) { public AuthMeServerListener(AuthMe plugin, Messages messages, PluginHooks pluginHooks, SpawnLoader spawnLoader) {
this.m = plugin.getMessages();
this.plugin = plugin; this.plugin = plugin;
this.messages = messages;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
} }
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
@ -31,11 +36,11 @@ public class AuthMeServerListener implements Listener {
if (!Settings.countriesBlacklist.isEmpty() || !Settings.countries.isEmpty()){ if (!Settings.countriesBlacklist.isEmpty() || !Settings.countries.isEmpty()){
String countryCode = GeoLiteAPI.getCountryCode(event.getAddress().getHostAddress()); String countryCode = GeoLiteAPI.getCountryCode(event.getAddress().getHostAddress());
if( Settings.countriesBlacklist.contains(countryCode)) { if( Settings.countriesBlacklist.contains(countryCode)) {
event.setMotd(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR)); event.setMotd(messages.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
return; return;
} }
if (Settings.enableProtection && !Settings.countries.contains(countryCode)) { if (Settings.enableProtection && !Settings.countries.contains(countryCode)) {
event.setMotd(m.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR)); event.setMotd(messages.retrieveSingle(MessageKey.COUNTRY_BANNED_ERROR));
} }
} }
} }
@ -47,38 +52,21 @@ public class AuthMeServerListener implements Listener {
return; return;
} }
// Get the plugin instance final String pluginName = event.getPlugin().getName();
Plugin pluginInstance = event.getPlugin(); if ("Essentials".equalsIgnoreCase(pluginName)) {
pluginHooks.unhookEssentials();
// Make sure it's not this plugin itself ConsoleLogger.info("Essentials has been disabled: unhooking");
if (pluginInstance.equals(this.plugin)) { } else if ("Multiverse-Core".equalsIgnoreCase(pluginName)) {
return; pluginHooks.unhookMultiverse();
ConsoleLogger.info("Multiverse-Core has been disabled: unhooking");
} else if ("CombatTagPlus".equalsIgnoreCase(pluginName)) {
pluginHooks.unhookCombatPlus();
ConsoleLogger.info("CombatTagPlus has been disabled: unhooking");
} else if ("EssentialsSpawn".equalsIgnoreCase(pluginName)) {
spawnLoader.unloadEssentialsSpawn();
ConsoleLogger.info("EssentialsSpawn has been disabled: unhooking");
} }
// Call the onPluginDisable method in the permissions manager
this.plugin.getPermissionsManager().onPluginDisable(event);
String pluginName = pluginInstance.getName();
if (pluginName.equalsIgnoreCase("Essentials")) {
plugin.ess = null;
ConsoleLogger.info("Essentials has been disabled, unhook!");
return;
}
if (pluginName.equalsIgnoreCase("EssentialsSpawn")) {
plugin.essentialsSpawn = null;
ConsoleLogger.info("EssentialsSpawn has been disabled, unhook!");
return;
}
if (pluginName.equalsIgnoreCase("Multiverse-Core")) {
plugin.multiverse = null;
ConsoleLogger.info("Multiverse-Core has been disabled, unhook!");
return;
}
if (pluginName.equalsIgnoreCase("CombatTagPlus")) {
plugin.combatTagPlus = null;
ConsoleLogger.info("CombatTagPlus has been disabled, unhook!");
return;
}
if (pluginName.equalsIgnoreCase("ProtocolLib")) { if (pluginName.equalsIgnoreCase("ProtocolLib")) {
plugin.inventoryProtector = null; plugin.inventoryProtector = null;
plugin.tablistHider = null; plugin.tablistHider = null;
@ -89,22 +77,22 @@ public class AuthMeServerListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onPluginEnable(PluginEnableEvent event) { public void onPluginEnable(PluginEnableEvent event) {
// Call the onPluginEnable method in the permissions manager // Make sure the plugin instance isn't null
this.plugin.getPermissionsManager().onPluginEnable(event); if (event.getPlugin() == null) {
return;
}
String pluginName = event.getPlugin().getName(); final String pluginName = event.getPlugin().getName();
if (pluginName.equalsIgnoreCase("Essentials") || pluginName.equalsIgnoreCase("EssentialsSpawn")) { if ("Essentials".equalsIgnoreCase(pluginName)) {
plugin.checkEssentials(); pluginHooks.tryHookToEssentials();
return; } else if ("Multiverse-Core".equalsIgnoreCase(pluginName)) {
} pluginHooks.tryHookToMultiverse();
if (pluginName.equalsIgnoreCase("Multiverse-Core")) { } else if ("CombatTagPlus".equalsIgnoreCase(pluginName)) {
plugin.checkMultiverse(); pluginHooks.tryHookToCombatPlus();
return; } else if ("EssentialsSpawn".equalsIgnoreCase(pluginName)) {
} spawnLoader.loadEssentialsSpawn();
if (pluginName.equalsIgnoreCase("CombatTagPlus")) {
plugin.checkCombatTagPlus();
return;
} }
if (pluginName.equalsIgnoreCase("ProtocolLib")) { if (pluginName.equalsIgnoreCase("ProtocolLib")) {
plugin.checkProtocolLib(); plugin.checkProtocolLib();
} }

View File

@ -29,11 +29,13 @@ public class AuthMeTablistPacketAdapter extends PacketAdapter {
} }
} }
// TODO: fix this in 1.9
public void register() { public void register() {
ProtocolLibrary.getProtocolManager().addPacketListener(this); ConsoleLogger.showError("The hideTablistBeforeLogin feature is temporarily disabled due to issues with 1.9 clients.");
//ProtocolLibrary.getProtocolManager().addPacketListener(this);
} }
public void unregister() { public void unregister() {
ProtocolLibrary.getProtocolManager().removePacketListener(this); //ProtocolLibrary.getProtocolManager().removePacketListener(this);
} }
} }

View File

@ -59,13 +59,16 @@ public class Log4JFilter implements Filter {
@Override @Override
public Result filter(Logger arg0, Level arg1, Marker arg2, String message, Object... arg4) { public Result filter(Logger arg0, Level arg1, Marker arg2, String message, Object... arg4) {
if (message == null) {
return Result.NEUTRAL;
}
return validateMessage(message); return validateMessage(message);
} }
@Override @Override
public Result filter(Logger arg0, Level arg1, Marker arg2, Object message, Throwable arg4) { public Result filter(Logger arg0, Level arg1, Marker arg2, Object message, Throwable arg4) {
if (message == null) { if (message == null) {
return Result.NEUTRAL; return Result.NEUTRAL;
} }
return validateMessage(message.toString()); return validateMessage(message.toString());
} }

View File

@ -41,7 +41,7 @@ public enum MessageKey {
REGISTER_EMAIL_MESSAGE("reg_email_msg"), REGISTER_EMAIL_MESSAGE("reg_email_msg"),
MAX_REGISTER_EXCEEDED("max_reg"), MAX_REGISTER_EXCEEDED("max_reg", "%max_acc", "%reg_count", "%reg_names"),
USAGE_REGISTER("usage_reg"), USAGE_REGISTER("usage_reg"),

View File

@ -96,6 +96,7 @@ public class Messages {
* *
* @param key The key of the message to send * @param key The key of the message to send
* @param replacements The replacements to apply for the tags * @param replacements The replacements to apply for the tags
* @return The message from the file with replacements
*/ */
public String retrieveSingle(MessageKey key, String... replacements) { public String retrieveSingle(MessageKey key, String... replacements) {
String message = retrieveSingle(key); String message = retrieveSingle(key);
@ -111,7 +112,7 @@ public class Messages {
} }
/** /**
* Reload the messages manager. * Reset the messages manager to retrieve messages from the given file instead of the current one.
* *
* @param messagesFile The new file to load messages from * @param messagesFile The new file to load messages from
*/ */

View File

@ -24,7 +24,6 @@ import de.bananaco.bpermissions.api.CalculableType;
import fr.xephi.authme.command.CommandDescription; import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.CollectionUtils;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
import ru.tehkode.permissions.PermissionManager;
import ru.tehkode.permissions.PermissionUser; import ru.tehkode.permissions.PermissionUser;
import ru.tehkode.permissions.bukkit.PermissionsEx; import ru.tehkode.permissions.bukkit.PermissionsEx;
@ -38,7 +37,7 @@ import ru.tehkode.permissions.bukkit.PermissionsEx;
* Written by Tim Visée. * Written by Tim Visée.
* </p> * </p>
* @author Tim Visée, http://timvisee.com * @author Tim Visée, http://timvisee.com
* @version 0.2.1 * @version 0.3
*/ */
public class PermissionsManager implements PermissionsService { public class PermissionsManager implements PermissionsService {
@ -59,9 +58,14 @@ public class PermissionsManager implements PermissionsService {
*/ */
private Logger log; private Logger log;
/** /**
* Type of permissions system that is currently used. * The permissions manager Bukkit listener instance.
*/ */
private PermissionsSystemType permsType = PermissionsSystemType.NONE; private PermissionsManagerBukkitListener bukkitListener;
/**
* Type of permissions system that is currently used.
* Null if no permissions system is hooked and/or used.
*/
private PermissionsSystemType permsType = null;
/** /**
* Essentials group manager instance. * Essentials group manager instance.
*/ */
@ -82,6 +86,21 @@ public class PermissionsManager implements PermissionsService {
this.server = server; this.server = server;
this.plugin = plugin; this.plugin = plugin;
this.log = log; this.log = log;
// Create and register the Bukkit listener on the server if it's valid
if(this.server != null) {
// Create the Bukkit listener
this.bukkitListener = new PermissionsManagerBukkitListener(this);
// Get the plugin manager instance
PluginManager pluginManager = this.server.getPluginManager();
// Register the Bukkit listener
pluginManager.registerEvents(this.bukkitListener, this.plugin);
// Show a status message.
//this.log.info("Started permission plugins state listener!");
}
} }
/** /**
@ -90,7 +109,7 @@ public class PermissionsManager implements PermissionsService {
* @return False if there isn't any permissions system used. * @return False if there isn't any permissions system used.
*/ */
public boolean isEnabled() { public boolean isEnabled() {
return !permsType.equals(PermissionsSystemType.NONE); return permsType != null;
} }
/** /**
@ -108,110 +127,96 @@ public class PermissionsManager implements PermissionsService {
* @return The detected permissions system. * @return The detected permissions system.
*/ */
public PermissionsSystemType setup() { public PermissionsSystemType setup() {
// Force-unhook from current hooked permissions systems
unhook();
// Define the plugin manager // Define the plugin manager
final PluginManager pm = this.server.getPluginManager(); final PluginManager pluginManager = this.server.getPluginManager();
// Reset used permissions system type // Reset used permissions system type flag
permsType = PermissionsSystemType.NONE; permsType = null;
// PermissionsEx, check if it's available // Loop through all the available permissions system types
try { for(PermissionsSystemType type : PermissionsSystemType.values()) {
Plugin pex = pm.getPlugin("PermissionsEx"); // Try to find and hook the current plugin if available, print an error if failed
if (pex != null) { try {
PermissionManager pexPerms = PermissionsEx.getPermissionManager(); // Try to find the plugin for the current permissions system
if (pexPerms != null) { Plugin plugin = pluginManager.getPlugin(type.getPluginName());
permsType = PermissionsSystemType.PERMISSIONS_EX;
System.out.println("[" + plugin.getName() + "] Hooked into PermissionsEx!"); // Make sure a plugin with this name was found
return permsType; if(plugin == null)
continue;
// Make sure the plugin is enabled before hooking
if(!plugin.isEnabled()) {
this.log.info("Not hooking into " + type.getName() + " because it's disabled!");
continue;
} }
}
} catch (Exception ex) {
// An error occurred, show a warning message
System.out.println("[" + plugin.getName() + "] Error while hooking into PermissionsEx!");
}
// PermissionsBukkit, check if it's available // Use the proper method to hook this plugin
try { switch(type) {
Plugin bukkitPerms = pm.getPlugin("PermissionsBukkit"); case PERMISSIONS_EX:
if (bukkitPerms != null) { // Get the permissions manager for PermissionsEx and make sure it isn't null
permsType = PermissionsSystemType.PERMISSIONS_BUKKIT; if(PermissionsEx.getPermissionManager() == null) {
System.out.println("[" + plugin.getName() + "] Hooked into PermissionsBukkit!"); this.log.info("Failed to hook into " + type.getName() + "!");
return permsType; continue;
} }
} catch (Exception ex) {
// An error occurred, show a warning message
System.out.println("[" + plugin.getName() + "] Error while hooking into PermissionsBukkit!");
}
// bPermissions, check if it's available break;
try {
Plugin bPerms = pm.getPlugin("bPermissions");
if (bPerms != null) {
permsType = PermissionsSystemType.B_PERMISSIONS;
System.out.println("[" + plugin.getName() + "] Hooked into bPermissions!");
return permsType;
}
} catch (Exception ex) {
// An error occurred, show a warning message
System.out.println("[" + plugin.getName() + "] Error while hooking into bPermissions!");
}
// Essentials Group Manager, check if it's available case ESSENTIALS_GROUP_MANAGER:
try { // Set the plugin instance
final Plugin groupManagerPlugin = pm.getPlugin("GroupManager"); groupManagerPerms = (GroupManager) plugin;
if (groupManagerPlugin != null && groupManagerPlugin.isEnabled()) { break;
permsType = PermissionsSystemType.ESSENTIALS_GROUP_MANAGER;
groupManagerPerms = (GroupManager) groupManagerPlugin;
System.out.println("[" + plugin.getName() + "] Hooked into Essentials Group Manager!");
return permsType;
}
} catch (Exception ex) {
// An error occurred, show a warning message
System.out.println("[" + plugin.getName() + "] Error while hooking into Essentials Group Manager!");
}
// zPermissions, check if it's available case Z_PERMISSIONS:
try { // Set the zPermissions service and make sure it's valid
Plugin zPerms = pm.getPlugin("zPermissions"); zPermissionsService = Bukkit.getServicesManager().load(ZPermissionsService.class);
if (zPerms != null) { if(zPermissionsService == null) {
zPermissionsService = Bukkit.getServicesManager().load(ZPermissionsService.class); this.log.info("Failed to hook into " + type.getName() + "!");
if (zPermissionsService != null) { continue;
permsType = PermissionsSystemType.Z_PERMISSIONS; }
System.out.println("[" + plugin.getName() + "] Hooked into zPermissions!");
return permsType; break;
case VAULT:
// Get the permissions provider service
RegisteredServiceProvider<Permission> permissionProvider = this.server.getServicesManager().getRegistration(Permission.class);
if (permissionProvider == null) {
this.log.info("Failed to hook into " + type.getName() + "!");
continue;
}
// Get the Vault provider and make sure it's valid
vaultPerms = permissionProvider.getProvider();
if(vaultPerms == null) {
this.log.info("Not using " + type.getName() + " because it's disabled!");
continue;
}
break;
default:
} }
// Set the hooked permissions system type
this.permsType = type;
// Show a success message
this.log.info("Hooked into " + type.getName() + "!");
// Return the used permissions system type
return type;
} catch (Exception ex) {
// An error occurred, show a warning message
this.log.info("Error while hooking into " + type.getName() + "!");
} }
} catch (Exception ex) {
// An error occurred, show a warning message
System.out.println("[" + plugin.getName() + "] Error while hooking into zPermissions!");
} }
// Vault, check if it's available // No recognized permissions system found, show a message and return
try { this.log.info("No supported permissions system found! Permissions are disabled!");
final Plugin vaultPlugin = pm.getPlugin("Vault"); return null;
if (vaultPlugin != null && vaultPlugin.isEnabled()) {
RegisteredServiceProvider<Permission> permissionProvider = this.server.getServicesManager().getRegistration(Permission.class);
if (permissionProvider != null) {
vaultPerms = permissionProvider.getProvider();
if (vaultPerms.isEnabled()) {
permsType = PermissionsSystemType.VAULT;
System.out.println("[" + plugin.getName() + "] Hooked into Vault Permissions!");
return permsType;
} else {
System.out.println("[" + plugin.getName() + "] Not using Vault Permissions, Vault Permissions is disabled!");
}
}
}
} catch (Exception ex) {
// An error occurred, show a warning message
System.out.println("[" + plugin.getName() + "] Error while hooking into Vault Permissions!");
}
// No recognized permissions system found
permsType = PermissionsSystemType.NONE;
System.out.println("[" + plugin.getName() + "] No supported permissions system found! Permissions disabled!");
return PermissionsSystemType.NONE;
} }
/** /**
@ -219,7 +224,7 @@ public class PermissionsManager implements PermissionsService {
*/ */
public void unhook() { public void unhook() {
// Reset the current used permissions system // Reset the current used permissions system
this.permsType = PermissionsSystemType.NONE; this.permsType = null;
// Print a status message to the console // Print a status message to the console
this.log.info("Unhooked from Permissions!"); this.log.info("Unhooked from Permissions!");
@ -277,7 +282,14 @@ public class PermissionsManager implements PermissionsService {
} }
} }
/**
* Get the permissions manager Bukkit listener instance.
*
* @return Listener instance.
*/
public PermissionsManagerBukkitListener getListener() {
return this.bukkitListener;
}
/** /**
* Check if the command sender has permission for the given permissions node. If no permissions system is used or * Check if the command sender has permission for the given permissions node. If no permissions system is used or
@ -383,13 +395,9 @@ public class PermissionsManager implements PermissionsService {
// Vault // Vault
return vaultPerms.has(player, permsNode); return vaultPerms.has(player, permsNode);
case NONE: default:
// Not hooked into any permissions system, return default // Not hooked into any permissions system, return default
return def; return def;
default:
// Something went wrong, return false to prevent problems
return false;
} }
} }
@ -416,12 +424,8 @@ public class PermissionsManager implements PermissionsService {
// Vault // Vault
return vaultPerms.hasGroupSupport(); return vaultPerms.hasGroupSupport();
case NONE:
// Not hooked into any permissions system, return false
return false;
default: default:
// Something went wrong, return false to prevent problems // Not hooked into any permissions system, return false
return false; return false;
} }
} }
@ -469,12 +473,8 @@ public class PermissionsManager implements PermissionsService {
// Vault // Vault
return Arrays.asList(vaultPerms.getPlayerGroups(player)); return Arrays.asList(vaultPerms.getPlayerGroups(player));
case NONE:
// Not hooked into any permissions system, return an empty list
return new ArrayList<>();
default: default:
// Something went wrong, return an empty list to prevent problems // Not hooked into any permissions system, return an empty list
return new ArrayList<>(); return new ArrayList<>();
} }
} }
@ -521,12 +521,8 @@ public class PermissionsManager implements PermissionsService {
// Vault // Vault
return vaultPerms.getPrimaryGroup(player); return vaultPerms.getPrimaryGroup(player);
case NONE:
// Not hooked into any permissions system, return null
return null;
default: default:
// Something went wrong, return null to prevent problems // Not hooked into any permissions system, return null
return null; return null;
} }
} }
@ -575,12 +571,8 @@ public class PermissionsManager implements PermissionsService {
// Vault // Vault
return vaultPerms.playerInGroup(player, groupName); return vaultPerms.playerInGroup(player, groupName);
case NONE:
// Not hooked into any permissions system, return an empty list
return false;
default: default:
// Something went wrong, return an empty list to prevent problems // Not hooked into any permissions system, return an empty list
return false; return false;
} }
} }
@ -632,12 +624,8 @@ public class PermissionsManager implements PermissionsService {
vaultPerms.playerAddGroup(player, groupName); vaultPerms.playerAddGroup(player, groupName);
return true; return true;
case NONE:
// Not hooked into any permissions system, return false
return false;
default: default:
// Something went wrong, return false // Not hooked into any permissions system, return false
return false; return false;
} }
} }
@ -713,12 +701,8 @@ public class PermissionsManager implements PermissionsService {
vaultPerms.playerRemoveGroup(player, groupName); vaultPerms.playerRemoveGroup(player, groupName);
return true; return true;
case NONE:
// Not hooked into any permissions system, return false
return false;
default: default:
// Something went wrong, return false // Not hooked into any permissions system, return false
return false; return false;
} }
} }
@ -802,12 +786,8 @@ public class PermissionsManager implements PermissionsService {
vaultPerms.playerAddGroup(player, groupName); vaultPerms.playerAddGroup(player, groupName);
return true; return true;
case NONE:
// Not hooked into any permissions system, return false
return false;
default: default:
// Something went wrong, return false // Not hooked into any permissions system, return false
return false; return false;
} }
} }
@ -867,6 +847,4 @@ public class PermissionsManager implements PermissionsService {
// Remove each group // Remove each group
return removeGroups(player, groupNames); return removeGroups(player, groupNames);
} }
} }

View File

@ -0,0 +1,85 @@
package fr.xephi.authme.permission;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
public class PermissionsManagerBukkitListener implements Listener {
/**
* The permissions manager instance.
*/
private PermissionsManager permissionsManager;
/**
* Whether the listener is enabled or not.
*/
private boolean enabled = true;
/**
* Constructor.\
*
* @param permissionsManager Permissions manager instance.
*/
public PermissionsManagerBukkitListener(PermissionsManager permissionsManager) {
this.permissionsManager = permissionsManager;
}
/**
* Check whether the listener is enabled.
*
* @return True if the listener is enabled.
*/
public boolean isEnabled() {
return this.enabled;
}
/**
* Set whether the listener is enabled.
* Disabling the listener will stop the event handling until it's enabled again.
*
* @param enabled True if enabled, false if disabled.
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
/**
* Called when a plugin is enabled.
*
* @param event Event reference.
*/
@EventHandler
public void onPluginEnable(PluginEnableEvent event) {
// Make sure the listener is enabled
if(!isEnabled())
return;
// Make sure the permissions manager is set
if(this.permissionsManager == null)
return;
// Call the onPluginEnable method in the permissions manager
permissionsManager.onPluginEnable(event);
}
/**
* Called when a plugin is disabled.
*
* @param event Event reference.
*/
@EventHandler
public void onPluginDisable(PluginDisableEvent event) {
// Make sure the listener is enabled
if(!isEnabled())
return;
// Make sure the permissions manager is set
if(this.permissionsManager == null)
return;
// Call the onPluginDisable method in the permissions manager
permissionsManager.onPluginDisable(event);
}
}

View File

@ -5,32 +5,82 @@ package fr.xephi.authme.permission;
*/ */
public enum PermissionsSystemType { public enum PermissionsSystemType {
NONE("None"), /**
* Permissions Ex.
*/
PERMISSIONS_EX("PermissionsEx", "PermissionsEx"),
PERMISSIONS_EX("PermissionsEx"), /**
* Permissions Bukkit.
*/
PERMISSIONS_BUKKIT("Permissions Bukkit", "PermissionsBukkit"),
PERMISSIONS_BUKKIT("Permissions Bukkit"), /**
* bPermissions.
*/
B_PERMISSIONS("bPermissions", "bPermissions"),
B_PERMISSIONS("bPermissions"), /**
* Essentials Group Manager.
*/
ESSENTIALS_GROUP_MANAGER("Essentials Group Manager", "GroupManager"),
ESSENTIALS_GROUP_MANAGER("Essentials Group Manager"), /**
* zPermissions.
*/
Z_PERMISSIONS("zPermissions", "zPermissions"),
Z_PERMISSIONS("zPermissions"), /**
* Vault.
*/
VAULT("Vault", "Vault");
VAULT("Vault"); /**
* The display name of the permissions system.
*/
public String name;
public final String name; /**
* The name of the permissions system plugin.
*/
public String pluginName;
/** /**
* Constructor for PermissionsSystemType. * Constructor for PermissionsSystemType.
* *
* @param name The name the permissions manager goes by * @param name Display name of the permissions system.
* @param pluginName Name of the plugin.
*/ */
PermissionsSystemType(String name) { PermissionsSystemType(String name, String pluginName) {
this.name = name; this.name = name;
this.pluginName = pluginName;
} }
/**
* Get the display name of the permissions system.
*
* @return Display name.
*/
public String getName() { public String getName() {
return this.name; return this.name;
} }
/**
* Return the plugin name.
*
* @return Plugin name.
*/
public String getPluginName() {
return this.pluginName;
}
/**
* Cast the permissions system type to a string.
*
* @return The display name of the permissions system.
*/
@Override
public String toString() {
return getName();
}
} }

View File

@ -55,10 +55,10 @@ public enum PlayerPermission implements PermissionNode {
*/ */
CAN_LOGIN_BE_FORCED("authme.player.canbeforced"), CAN_LOGIN_BE_FORCED("authme.player.canbeforced"),
/** /**
* Permission to use to see own other accounts. * Permission to use to see own other accounts.
*/ */
SEE_OWN_ACCOUNTS("authme.player.seeownaccounts"); SEE_OWN_ACCOUNTS("authme.player.seeownaccounts");
/** /**
* The permission node. * The permission node.

View File

@ -2,6 +2,7 @@ package fr.xephi.authme.process;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.process.email.AsyncAddEmail; import fr.xephi.authme.process.email.AsyncAddEmail;
import fr.xephi.authme.process.email.AsyncChangeEmail; import fr.xephi.authme.process.email.AsyncChangeEmail;
import fr.xephi.authme.process.join.AsynchronousJoin; import fr.xephi.authme.process.join.AsynchronousJoin;
@ -10,7 +11,6 @@ import fr.xephi.authme.process.logout.AsynchronousLogout;
import fr.xephi.authme.process.quit.AsynchronousQuit; import fr.xephi.authme.process.quit.AsynchronousQuit;
import fr.xephi.authme.process.register.AsyncRegister; import fr.xephi.authme.process.register.AsyncRegister;
import fr.xephi.authme.process.unregister.AsynchronousUnregister; import fr.xephi.authme.process.unregister.AsynchronousUnregister;
import fr.xephi.authme.settings.NewSetting;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
@ -20,99 +20,51 @@ public class Management {
private final AuthMe plugin; private final AuthMe plugin;
private final BukkitScheduler sched; private final BukkitScheduler sched;
private final NewSetting settings; private final ProcessService processService;
private final DataSource dataSource;
private final PlayerCache playerCache;
/** public Management(AuthMe plugin, ProcessService processService, DataSource dataSource, PlayerCache playerCache) {
* Constructor for Management.
*
* @param plugin AuthMe
* @param settings The plugin settings
*/
public Management(AuthMe plugin, NewSetting settings) {
this.plugin = plugin; this.plugin = plugin;
this.sched = this.plugin.getServer().getScheduler(); this.sched = this.plugin.getServer().getScheduler();
this.settings = settings; this.processService = processService;
this.dataSource = dataSource;
this.playerCache = playerCache;
} }
public void performLogin(final Player player, final String password, final boolean forceLogin) { public void performLogin(final Player player, final String password, final boolean forceLogin) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsynchronousLogin(player, password, forceLogin, plugin, dataSource, processService));
@Override
public void run() {
new AsynchronousLogin(player, password, forceLogin, plugin, plugin.getDataSource(), settings)
.process();
}
});
} }
public void performLogout(final Player player) { public void performLogout(final Player player) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsynchronousLogout(player, plugin, dataSource, processService));
@Override
public void run() {
new AsynchronousLogout(player, plugin, plugin.getDataSource()).process();
}
});
} }
public void performRegister(final Player player, final String password, final String email) { public void performRegister(final Player player, final String password, final String email) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsyncRegister(player, password, email, plugin, dataSource, processService));
@Override
public void run() {
new AsyncRegister(player, password, email, plugin, plugin.getDataSource(), settings).process();
}
});
} }
public void performUnregister(final Player player, final String password, final boolean force) { public void performUnregister(final Player player, final String password, final boolean force) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsynchronousUnregister(player, password, force, plugin, processService));
@Override
public void run() {
new AsynchronousUnregister(player, password, force, plugin).process();
}
});
} }
public void performJoin(final Player player) { public void performJoin(final Player player) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsynchronousJoin(player, plugin, dataSource, playerCache, processService));
@Override
public void run() {
new AsynchronousJoin(player, plugin, plugin.getDataSource()).process();
}
});
} }
public void performQuit(final Player player, final boolean isKick) { public void performQuit(final Player player, final boolean isKick) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsynchronousQuit(player, plugin, dataSource, isKick, processService));
@Override
public void run() {
new AsynchronousQuit(player, plugin, plugin.getDataSource(), isKick).process();
}
});
} }
public void performAddEmail(final Player player, final String newEmail) { public void performAddEmail(final Player player, final String newEmail) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsyncAddEmail(player, newEmail, dataSource, playerCache, processService));
@Override
public void run() {
new AsyncAddEmail(player, plugin, newEmail, plugin.getDataSource(),
PlayerCache.getInstance(), settings).process();
}
});
} }
public void performChangeEmail(final Player player, final String oldEmail, final String newEmail) { public void performChangeEmail(final Player player, final String oldEmail, final String newEmail) {
sched.runTaskAsynchronously(plugin, new Runnable() { runTask(new AsyncChangeEmail(player, oldEmail, newEmail, dataSource, playerCache, processService));
@Override }
public void run() {
new AsyncChangeEmail(player, plugin, oldEmail, newEmail, plugin.getDataSource(), PlayerCache.getInstance(), settings).process(); private void runTask(Process process) {
} sched.runTaskAsynchronously(plugin, process);
});
} }
} }

View File

@ -0,0 +1,8 @@
package fr.xephi.authme.process;
/**
* Common interface for AuthMe processes.
*/
public interface Process extends Runnable {
}

View File

@ -0,0 +1,202 @@
package fr.xephi.authme.process;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.IpAddressManager;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.SpawnLoader;
import fr.xephi.authme.settings.domain.Property;
import org.bukkit.command.CommandSender;
import org.bukkit.event.Event;
import org.bukkit.scheduler.BukkitTask;
/**
* Service for asynchronous and synchronous processes.
*/
public class ProcessService {
private final NewSetting settings;
private final Messages messages;
private final AuthMe authMe;
private final DataSource dataSource;
private final IpAddressManager ipAddressManager;
private final PasswordSecurity passwordSecurity;
private final PluginHooks pluginHooks;
private final SpawnLoader spawnLoader;
public ProcessService(NewSetting settings, Messages messages, AuthMe authMe, DataSource dataSource,
IpAddressManager ipAddressManager, PasswordSecurity passwordSecurity, PluginHooks pluginHooks,
SpawnLoader spawnLoader) {
this.settings = settings;
this.messages = messages;
this.authMe = authMe;
this.dataSource = dataSource;
this.ipAddressManager = ipAddressManager;
this.passwordSecurity = passwordSecurity;
this.pluginHooks = pluginHooks;
this.spawnLoader = spawnLoader;
}
/**
* Retrieve a property's value.
*
* @param property the property to retrieve
* @param <T> the property type
* @return the property's value
*/
public <T> T getProperty(Property<T> property) {
return settings.getProperty(property);
}
/**
* Return the settings manager.
*
* @return settings manager
*/
public NewSetting getSettings() {
return settings;
}
/**
* Send a message to the command sender.
*
* @param sender the command sender
* @param key the message key
*/
public void send(CommandSender sender, MessageKey key) {
messages.send(sender, key);
}
/**
* Send a message to the command sender with the given replacements.
*
* @param sender the command sender
* @param key the message key
* @param replacements the replacements to apply to the message
*/
public void send(CommandSender sender, MessageKey key, String... replacements) {
messages.send(sender, key, replacements);
}
/**
* Retrieve a message.
*
* @param key the key of the message
* @return the message, split by line
*/
public String[] retrieveMessage(MessageKey key) {
return messages.retrieve(key);
}
/**
* Retrieve a message as one piece.
*
* @param key the key of the message
* @return the message
*/
public String retrieveSingleMessage(MessageKey key) {
return messages.retrieveSingle(key);
}
/**
* Run a task.
*
* @param task the task to run
* @return the assigned task id
*/
public BukkitTask runTask(Runnable task) {
return authMe.getServer().getScheduler().runTask(authMe, task);
}
/**
* Run a task at a later time.
*
* @param task the task to run
* @param delay the delay before running the task
* @return the assigned task id
*/
public BukkitTask runTaskLater(Runnable task, long delay) {
return authMe.getServer().getScheduler().runTaskLater(authMe, task, delay);
}
/**
* Schedule a synchronous delayed task.
*
* @param task the task to schedule
* @return the task id
*/
public int scheduleSyncDelayedTask(Runnable task) {
return authMe.getServer().getScheduler().scheduleSyncDelayedTask(authMe, task);
}
/**
* Emit an event.
*
* @param event the event to emit
*/
public void callEvent(Event event) {
authMe.getServer().getPluginManager().callEvent(event);
}
/**
* Return the plugin instance.
*
* @return AuthMe instance
*/
public AuthMe getAuthMe() {
return authMe;
}
/**
* Return the IP address manager.
*
* @return the ip address manager
*/
public IpAddressManager getIpAddressManager() {
return ipAddressManager;
}
/**
* Compute the hash for the given password.
*
* @param password the password to hash
* @param username the user to hash for
* @return the resulting hash
*/
public HashedPassword computeHash(String password, String username) {
return passwordSecurity.computeHash(password, username);
}
/**
* Return the PluginHooks manager.
*
* @return PluginHooks instance
*/
public PluginHooks getPluginHooks() {
return pluginHooks;
}
/**
* Return the spawn manager.
*
* @return SpawnLoader instance
*/
public SpawnLoader getSpawnLoader() {
return spawnLoader;
}
/**
* Return the plugin's datasource.
*
* @return the datasource
*/
public DataSource getDataSource() {
return dataSource;
}
}

View File

@ -1,40 +1,38 @@
package fr.xephi.authme.process.email; package fr.xephi.authme.process.email;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Process;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
/** /**
* Async task to add an email to an account. * Async task to add an email to an account.
*/ */
public class AsyncAddEmail { public class AsyncAddEmail implements Process {
private final Player player; private final Player player;
private final String email; private final String email;
private final Messages messages; private final ProcessService service;
private final DataSource dataSource; private final DataSource dataSource;
private final PlayerCache playerCache; private final PlayerCache playerCache;
private final NewSetting settings;
public AsyncAddEmail(Player player, AuthMe plugin, String email, DataSource dataSource, public AsyncAddEmail(Player player, String email, DataSource dataSource, PlayerCache playerCache,
PlayerCache playerCache, NewSetting settings) { ProcessService service) {
this.messages = plugin.getMessages();
this.player = player; this.player = player;
this.email = email; this.email = email;
this.dataSource = dataSource; this.dataSource = dataSource;
this.playerCache = playerCache; this.playerCache = playerCache;
this.settings = settings; this.service = service;
} }
public void process() { @Override
public void run() {
String playerName = player.getName().toLowerCase(); String playerName = player.getName().toLowerCase();
if (playerCache.isAuthenticated(playerName)) { if (playerCache.isAuthenticated(playerName)) {
@ -42,19 +40,19 @@ public class AsyncAddEmail {
final String currentEmail = auth.getEmail(); final String currentEmail = auth.getEmail();
if (currentEmail != null && !"your@email.com".equals(currentEmail)) { if (currentEmail != null && !"your@email.com".equals(currentEmail)) {
messages.send(player, MessageKey.USAGE_CHANGE_EMAIL); service.send(player, MessageKey.USAGE_CHANGE_EMAIL);
} else if (!Utils.isEmailCorrect(email, settings)) { } else if (!Utils.isEmailCorrect(email, service.getSettings())) {
messages.send(player, MessageKey.INVALID_EMAIL); service.send(player, MessageKey.INVALID_EMAIL);
} else if (dataSource.isEmailStored(email)) { } else if (dataSource.isEmailStored(email)) {
messages.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR); service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
} else { } else {
auth.setEmail(email); auth.setEmail(email);
if (dataSource.updateEmail(auth)) { if (dataSource.updateEmail(auth)) {
playerCache.updatePlayer(auth); playerCache.updatePlayer(auth);
messages.send(player, MessageKey.EMAIL_ADDED_SUCCESS); service.send(player, MessageKey.EMAIL_ADDED_SUCCESS);
} else { } else {
ConsoleLogger.showError("Could not save email for player '" + player + "'"); ConsoleLogger.showError("Could not save email for player '" + player + "'");
messages.send(player, MessageKey.ERROR); service.send(player, MessageKey.ERROR);
} }
} }
} else { } else {
@ -64,11 +62,11 @@ public class AsyncAddEmail {
private void sendUnloggedMessage(DataSource dataSource) { private void sendUnloggedMessage(DataSource dataSource) {
if (dataSource.isAuthAvailable(player.getName())) { if (dataSource.isAuthAvailable(player.getName())) {
messages.send(player, MessageKey.LOGIN_MESSAGE); service.send(player, MessageKey.LOGIN_MESSAGE);
} else if (Settings.emailRegistration) { } else if (service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)) {
messages.send(player, MessageKey.REGISTER_EMAIL_MESSAGE); service.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
} else { } else {
messages.send(player, MessageKey.REGISTER_MESSAGE); service.send(player, MessageKey.REGISTER_MESSAGE);
} }
} }

View File

@ -1,54 +1,52 @@
package fr.xephi.authme.process.email; package fr.xephi.authme.process.email;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Process;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
/** /**
* Async task for changing the email. * Async task for changing the email.
*/ */
public class AsyncChangeEmail { public class AsyncChangeEmail implements Process {
private final Player player; private final Player player;
private final String oldEmail; private final String oldEmail;
private final String newEmail; private final String newEmail;
private final Messages m; private final ProcessService service;
private final NewSetting settings;
private final PlayerCache playerCache; private final PlayerCache playerCache;
private final DataSource dataSource; private final DataSource dataSource;
public AsyncChangeEmail(Player player, AuthMe plugin, String oldEmail, String newEmail, DataSource dataSource, public AsyncChangeEmail(Player player, String oldEmail, String newEmail, DataSource dataSource,
PlayerCache playerCache, NewSetting settings) { PlayerCache playerCache, ProcessService service) {
this.m = plugin.getMessages();
this.player = player; this.player = player;
this.oldEmail = oldEmail; this.oldEmail = oldEmail;
this.newEmail = newEmail; this.newEmail = newEmail;
this.playerCache = playerCache; this.playerCache = playerCache;
this.dataSource = dataSource; this.dataSource = dataSource;
this.settings = settings; this.service = service;
} }
public void process() { @Override
public void run() {
String playerName = player.getName().toLowerCase(); String playerName = player.getName().toLowerCase();
if (playerCache.isAuthenticated(playerName)) { if (playerCache.isAuthenticated(playerName)) {
PlayerAuth auth = playerCache.getAuth(playerName); PlayerAuth auth = playerCache.getAuth(playerName);
final String currentEmail = auth.getEmail(); final String currentEmail = auth.getEmail();
if (currentEmail == null) { if (currentEmail == null) {
m.send(player, MessageKey.USAGE_ADD_EMAIL); service.send(player, MessageKey.USAGE_ADD_EMAIL);
} else if (newEmail == null || !Utils.isEmailCorrect(newEmail, settings)) { } else if (newEmail == null || !Utils.isEmailCorrect(newEmail, service.getSettings())) {
m.send(player, MessageKey.INVALID_NEW_EMAIL); service.send(player, MessageKey.INVALID_NEW_EMAIL);
} else if (!oldEmail.equals(currentEmail)) { } else if (!oldEmail.equals(currentEmail)) {
m.send(player, MessageKey.INVALID_OLD_EMAIL); service.send(player, MessageKey.INVALID_OLD_EMAIL);
} else if (dataSource.isEmailStored(newEmail)) { } else if (dataSource.isEmailStored(newEmail)) {
m.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR); service.send(player, MessageKey.EMAIL_ALREADY_USED_ERROR);
} else { } else {
saveNewEmail(auth); saveNewEmail(auth);
} }
@ -61,20 +59,20 @@ public class AsyncChangeEmail {
auth.setEmail(newEmail); auth.setEmail(newEmail);
if (dataSource.updateEmail(auth)) { if (dataSource.updateEmail(auth)) {
playerCache.updatePlayer(auth); playerCache.updatePlayer(auth);
m.send(player, MessageKey.EMAIL_CHANGED_SUCCESS); service.send(player, MessageKey.EMAIL_CHANGED_SUCCESS);
} else { } else {
m.send(player, MessageKey.ERROR); service.send(player, MessageKey.ERROR);
auth.setEmail(newEmail); auth.setEmail(newEmail);
} }
} }
private void outputUnloggedMessage() { private void outputUnloggedMessage() {
if (dataSource.isAuthAvailable(player.getName())) { if (dataSource.isAuthAvailable(player.getName())) {
m.send(player, MessageKey.LOGIN_MESSAGE); service.send(player, MessageKey.LOGIN_MESSAGE);
} else if (Settings.emailRegistration) { } else if (service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)) {
m.send(player, MessageKey.REGISTER_EMAIL_MESSAGE); service.send(player, MessageKey.REGISTER_EMAIL_MESSAGE);
} else { } else {
m.send(player, MessageKey.REGISTER_MESSAGE); service.send(player, MessageKey.REGISTER_MESSAGE);
} }
} }
} }

View File

@ -11,66 +11,64 @@ import fr.xephi.authme.events.ProtectInventoryEvent;
import fr.xephi.authme.events.SpawnTeleportEvent; import fr.xephi.authme.events.SpawnTeleportEvent;
import fr.xephi.authme.listener.AuthMePlayerListener; import fr.xephi.authme.listener.AuthMePlayerListener;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.Spawn; import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.Utils.GroupType; import fr.xephi.authme.util.Utils.GroupType;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
/** /**
*/ */
public class AsynchronousJoin { public class AsynchronousJoin implements Process {
private final AuthMe plugin; private final AuthMe plugin;
private final Player player; private final Player player;
private final DataSource database; private final DataSource database;
private final String name; private final String name;
private final Messages m; private final ProcessService service;
private final BukkitScheduler sched; private final PlayerCache playerCache;
public AsynchronousJoin(Player player, AuthMe plugin, DataSource database) { public AsynchronousJoin(Player player, AuthMe plugin, DataSource database, PlayerCache playerCache,
this.m = plugin.getMessages(); ProcessService service) {
this.player = player; this.player = player;
this.plugin = plugin; this.plugin = plugin;
this.sched = plugin.getServer().getScheduler();
this.database = database; this.database = database;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.service = service;
this.playerCache = playerCache;
} }
public void process() { @Override
public void run() {
if (Utils.isUnrestricted(player)) { if (Utils.isUnrestricted(player)) {
return; return;
} }
if (Settings.checkVeryGames) { if (service.getProperty(HooksSettings.DISABLE_SOCIAL_SPY)) {
plugin.getVerygamesIp(player); service.getPluginHooks().setEssentialsSocialSpyStatus(player, false);
} }
if (plugin.ess != null && Settings.disableSocialSpy) { final String ip = service.getIpAddressManager().getPlayerIp(player);
plugin.ess.getUser(player).setSocialSpyEnabled(false); if (isNameRestricted(name, ip, player.getAddress().getHostName(), service.getSettings())) {
} service.scheduleSyncDelayedTask(new Runnable() {
final String ip = plugin.getIP(player);
if (Settings.isAllowRestrictedIp && isNameRestricted(name, ip, player.getAddress().getHostName())) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() {
@Override @Override
public void run() { public void run() {
AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true); AuthMePlayerListener.causeByAuthMe.putIfAbsent(name, true);
player.kickPlayer(m.retrieveSingle(MessageKey.NOT_OWNER_ERROR)); player.kickPlayer(service.retrieveSingleMessage(MessageKey.NOT_OWNER_ERROR));
if (Settings.banUnsafeIp) { if (Settings.banUnsafeIp) {
plugin.getServer().banIP(ip); plugin.getServer().banIP(ip);
} }
@ -78,38 +76,34 @@ public class AsynchronousJoin {
}); });
return; return;
} }
if (Settings.getMaxJoinPerIp > 0 if (service.getProperty(RestrictionSettings.MAX_JOIN_PER_IP) > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS) && !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& !ip.equalsIgnoreCase("127.0.0.1") && !"127.0.0.1".equalsIgnoreCase(ip)
&& !ip.equalsIgnoreCase("localhost") && !"localhost".equalsIgnoreCase(ip)
&& plugin.hasJoinedIp(player.getName(), ip)) { && hasJoinedIp(player.getName(), ip, service.getSettings())) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
player.kickPlayer("A player with the same IP is already in game!"); player.kickPlayer("A player with the same IP is already in game!");
} }
}); });
return; return;
} }
final Location spawnLoc = plugin.getSpawnLocation(player); final Location spawnLoc = service.getSpawnLoader().getSpawnLocation(player);
final boolean isAuthAvailable = database.isAuthAvailable(name); final boolean isAuthAvailable = database.isAuthAvailable(name);
if (isAuthAvailable) { if (isAuthAvailable) {
if (!Settings.noTeleport) { if (!Settings.noTeleport) {
if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) { if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name)); SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, playerCache.isAuthenticated(name));
plugin.getServer().getPluginManager().callEvent(tpEvent); service.callEvent(tpEvent);
if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null
&& tpEvent.getTo().getWorld() != null) { && tpEvent.getTo().getWorld() != null) {
player.teleport(tpEvent.getTo()); player.teleport(tpEvent.getTo());
} }
} }
}); });
} }
} }
@ -123,12 +117,12 @@ public class AsynchronousJoin {
if (ev.isCancelled()) { if (ev.isCancelled()) {
plugin.inventoryProtector.sendInventoryPacket(player); plugin.inventoryProtector.sendInventoryPacket(player);
if (!Settings.noConsoleSpam) { if (!Settings.noConsoleSpam) {
ConsoleLogger.info("ProtectInventoryEvent has been cancelled for " + player.getName() + " ..."); ConsoleLogger.info("ProtectInventoryEvent has been cancelled for " + player.getName() + "...");
} }
} }
} }
if (Settings.isSessionsEnabled && (PlayerCache.getInstance().isAuthenticated(name) || database.isLogged(name))) { if (service.getProperty(PluginSettings.SESSIONS_ENABLED) && (playerCache.isAuthenticated(name) || database.isLogged(name))) {
if (plugin.sessions.containsKey(name)) { if (plugin.sessions.containsKey(name)) {
plugin.sessions.get(name).cancel(); plugin.sessions.get(name).cancel();
plugin.sessions.remove(name); plugin.sessions.remove(name);
@ -137,11 +131,11 @@ public class AsynchronousJoin {
database.setUnlogged(name); database.setUnlogged(name);
PlayerCache.getInstance().removePlayer(name); PlayerCache.getInstance().removePlayer(name);
if (auth != null && auth.getIp().equals(ip)) { if (auth != null && auth.getIp().equals(ip)) {
m.send(player, MessageKey.SESSION_RECONNECTION); service.send(player, MessageKey.SESSION_RECONNECTION);
plugin.getManagement().performLogin(player, "dontneed", true); plugin.getManagement().performLogin(player, "dontneed", true);
return; return;
} else if (Settings.sessionExpireOnIpChange) { } else if (Settings.sessionExpireOnIpChange) {
m.send(player, MessageKey.SESSION_EXPIRED); service.send(player, MessageKey.SESSION_EXPIRED);
} }
} }
} else { } else {
@ -154,21 +148,18 @@ public class AsynchronousJoin {
if (!Settings.noTeleport && !needFirstSpawn() && Settings.isTeleportToSpawnEnabled if (!Settings.noTeleport && !needFirstSpawn() && Settings.isTeleportToSpawnEnabled
|| (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) { || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) {
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name)); SpawnTeleportEvent tpEvent = new SpawnTeleportEvent(player, player.getLocation(), spawnLoc, PlayerCache.getInstance().isAuthenticated(name));
plugin.getServer().getPluginManager().callEvent(tpEvent); service.callEvent(tpEvent);
if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null if (!tpEvent.isCancelled() && player.isOnline() && tpEvent.getTo() != null
&& tpEvent.getTo().getWorld() != null) { && tpEvent.getTo().getWorld() != null) {
player.teleport(tpEvent.getTo()); player.teleport(tpEvent.getTo());
}
} }
}
}); });
} }
} }
if (!LimboCache.getInstance().hasLimboPlayer(name)) { if (!LimboCache.getInstance().hasLimboPlayer(name)) {
@ -176,9 +167,9 @@ public class AsynchronousJoin {
} }
Utils.setGroup(player, isAuthAvailable ? GroupType.NOTLOGGEDIN : GroupType.UNREGISTERED); Utils.setGroup(player, isAuthAvailable ? GroupType.NOTLOGGEDIN : GroupType.UNREGISTERED);
final int timeOut = Settings.getRegistrationTimeout * 20; final int registrationTimeout = service.getProperty(RestrictionSettings.TIMEOUT) * 20;
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
player.setOp(false); player.setOp(false);
@ -186,28 +177,23 @@ public class AsynchronousJoin {
player.setFlySpeed(0.0f); player.setFlySpeed(0.0f);
player.setWalkSpeed(0.0f); player.setWalkSpeed(0.0f);
} }
player.setNoDamageTicks(timeOut); player.setNoDamageTicks(registrationTimeout);
if (Settings.useEssentialsMotd) { if (service.getProperty(HooksSettings.USE_ESSENTIALS_MOTD)) {
player.performCommand("motd"); player.performCommand("motd");
} }
if (Settings.applyBlindEffect) { if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
int blindTimeOut;
// Allow infinite blindness effect // Allow infinite blindness effect
if (timeOut <= 0) { int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
blindTimeOut = 99999;
} else {
blindTimeOut = timeOut;
}
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2)); player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
} }
} }
}); });
int msgInterval = Settings.getWarnMessageInterval; int msgInterval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
if (timeOut > 0) { if (registrationTimeout > 0) {
BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name, player), timeOut); BukkitTask id = service.runTaskLater(new TimeoutTask(plugin, name, player), registrationTimeout);
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id); LimboCache.getInstance().getLimboPlayer(name).setTimeoutTask(id);
} }
MessageKey msg; MessageKey msg;
@ -219,29 +205,30 @@ public class AsynchronousJoin {
: MessageKey.REGISTER_MESSAGE; : MessageKey.REGISTER_MESSAGE;
} }
if (msgInterval > 0 && LimboCache.getInstance().getLimboPlayer(name) != null) { if (msgInterval > 0 && LimboCache.getInstance().getLimboPlayer(name) != null) {
BukkitTask msgTask = sched.runTask(plugin, new MessageTask(plugin, name, msg, msgInterval)); BukkitTask msgTask = service.runTask(new MessageTask(plugin, name, msg, msgInterval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgTask); LimboCache.getInstance().getLimboPlayer(name).setMessageTask(msgTask);
} }
} }
private boolean needFirstSpawn() { private boolean needFirstSpawn() {
if (player.hasPlayedBefore()) if (player.hasPlayedBefore()) {
return false; return false;
Location firstSpawn = Spawn.getInstance().getFirstSpawn(); }
if (firstSpawn == null || firstSpawn.getWorld() == null) Location firstSpawn = service.getSpawnLoader().getFirstSpawn();
if (firstSpawn == null) {
return false; return false;
}
FirstSpawnTeleportEvent tpEvent = new FirstSpawnTeleportEvent(player, player.getLocation(), firstSpawn); FirstSpawnTeleportEvent tpEvent = new FirstSpawnTeleportEvent(player, player.getLocation(), firstSpawn);
plugin.getServer().getPluginManager().callEvent(tpEvent); plugin.getServer().getPluginManager().callEvent(tpEvent);
if (!tpEvent.isCancelled()) { if (!tpEvent.isCancelled()) {
if (player.isOnline() && tpEvent.getTo() != null && tpEvent.getTo().getWorld() != null) { if (player.isOnline() && tpEvent.getTo() != null && tpEvent.getTo().getWorld() != null) {
final Location fLoc = tpEvent.getTo(); final Location fLoc = tpEvent.getTo();
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
player.teleport(fLoc); player.teleport(fLoc);
} }
}); });
} }
} }
@ -249,25 +236,23 @@ public class AsynchronousJoin {
} }
private void placePlayerSafely(final Player player, final Location spawnLoc) { private void placePlayerSafely(final Player player, final Location spawnLoc) {
if (spawnLoc == null) if (spawnLoc == null || service.getProperty(RestrictionSettings.NO_TELEPORT))
return;
if (!Settings.noTeleport)
return; return;
if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName()))) if (Settings.isTeleportToSpawnEnabled || (Settings.isForceSpawnLocOnJoinEnabled && Settings.getForcedWorlds.contains(player.getWorld().getName())))
return; return;
if (!player.hasPlayedBefore()) if (!player.hasPlayedBefore())
return; return;
sched.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
if (spawnLoc.getWorld() == null) { if (spawnLoc.getWorld() == null) {
return; return;
} }
Material cur = player.getLocation().getBlock().getType(); Material cur = player.getLocation().getBlock().getType();
Material top = player.getLocation().add(0D, 1D, 0D).getBlock().getType(); Material top = player.getLocation().add(0, 1, 0).getBlock().getType();
if (cur == Material.PORTAL || cur == Material.ENDER_PORTAL if (cur == Material.PORTAL || cur == Material.ENDER_PORTAL
|| top == Material.PORTAL || top == Material.ENDER_PORTAL) { || top == Material.PORTAL || top == Material.ENDER_PORTAL) {
m.send(player, MessageKey.UNSAFE_QUIT_LOCATION); service.send(player, MessageKey.UNSAFE_QUIT_LOCATION);
player.teleport(spawnLoc); player.teleport(spawnLoc);
} }
} }
@ -281,12 +266,17 @@ public class AsynchronousJoin {
* @param name The name to check * @param name The name to check
* @param ip The IP address of the player * @param ip The IP address of the player
* @param domain The hostname of the IP address * @param domain The hostname of the IP address
* @param settings The settings instance
* @return True if the name is restricted (IP/domain is not allowed for the given name), * @return True if the name is restricted (IP/domain is not allowed for the given name),
* false if the restrictions are met or if the name has no restrictions to it * false if the restrictions are met or if the name has no restrictions to it
*/ */
private static boolean isNameRestricted(String name, String ip, String domain) { private static boolean isNameRestricted(String name, String ip, String domain, NewSetting settings) {
if (!settings.getProperty(RestrictionSettings.ENABLE_RESTRICTED_USERS)) {
return false;
}
boolean nameFound = false; boolean nameFound = false;
for (String entry : Settings.getRestrictedIp) { for (String entry : settings.getProperty(RestrictionSettings.ALLOWED_RESTRICTED_USERS)) {
String[] args = entry.split(";"); String[] args = entry.split(";");
String testName = args[0]; String testName = args[0];
String testIp = args[1]; String testIp = args[1];
@ -301,4 +291,14 @@ public class AsynchronousJoin {
return nameFound; return nameFound;
} }
private boolean hasJoinedIp(String name, String ip, NewSetting settings) {
int count = 0;
for (Player player : Utils.getOnlinePlayers()) {
if (ip.equalsIgnoreCase(service.getIpAddressManager().getPlayerIp(player))
&& !player.getName().equalsIgnoreCase(name)) {
count++;
}
}
return count >= settings.getProperty(RestrictionSettings.MAX_JOIN_PER_IP);
}
} }

View File

@ -5,17 +5,21 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.events.AuthMeAsyncPreLoginEvent; import fr.xephi.authme.events.AuthMeAsyncPreLoginEvent;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.AdminPermission; import fr.xephi.authme.permission.AdminPermission;
import fr.xephi.authme.permission.PlayerPermission; import fr.xephi.authme.permission.PlayerPermission;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.security.RandomString; import fr.xephi.authme.security.RandomString;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
@ -27,7 +31,7 @@ import java.util.List;
/** /**
*/ */
public class AsynchronousLogin { public class AsynchronousLogin implements Process {
private final Player player; private final Player player;
private final String name; private final String name;
@ -36,23 +40,11 @@ public class AsynchronousLogin {
private final boolean forceLogin; private final boolean forceLogin;
private final AuthMe plugin; private final AuthMe plugin;
private final DataSource database; private final DataSource database;
private final Messages m;
private final String ip; private final String ip;
private final NewSetting settings; private final ProcessService service;
/**
* Constructor for AsynchronousLogin.
*
* @param player Player
* @param password String
* @param forceLogin boolean
* @param plugin AuthMe
* @param data DataSource
* @param settings The settings
*/
public AsynchronousLogin(Player player, String password, boolean forceLogin, AuthMe plugin, DataSource data, public AsynchronousLogin(Player player, String password, boolean forceLogin, AuthMe plugin, DataSource data,
NewSetting settings) { ProcessService service) {
this.m = plugin.getMessages();
this.player = player; this.player = player;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.password = password; this.password = password;
@ -60,12 +52,12 @@ public class AsynchronousLogin {
this.forceLogin = forceLogin; this.forceLogin = forceLogin;
this.plugin = plugin; this.plugin = plugin;
this.database = data; this.database = data;
this.ip = plugin.getIP(player); this.ip = service.getIpAddressManager().getPlayerIp(player);
this.settings = settings; this.service = service;
} }
private boolean needsCaptcha() { private boolean needsCaptcha() {
if (Settings.useCaptcha) { if (service.getProperty(SecuritySettings.USE_CAPTCHA)) {
if (!plugin.captcha.containsKey(name)) { if (!plugin.captcha.containsKey(name)) {
plugin.captcha.putIfAbsent(name, 1); plugin.captcha.putIfAbsent(name, 1);
} else { } else {
@ -75,7 +67,7 @@ public class AsynchronousLogin {
} }
if (plugin.captcha.containsKey(name) && plugin.captcha.get(name) > Settings.maxLoginTry) { if (plugin.captcha.containsKey(name) && plugin.captcha.get(name) > Settings.maxLoginTry) {
plugin.cap.putIfAbsent(name, RandomString.generate(Settings.captchaLength)); plugin.cap.putIfAbsent(name, RandomString.generate(Settings.captchaLength));
m.send(player, MessageKey.USAGE_CAPTCHA, plugin.cap.get(name)); service.send(player, MessageKey.USAGE_CAPTCHA, plugin.cap.get(name));
return true; return true;
} }
} }
@ -90,30 +82,29 @@ public class AsynchronousLogin {
*/ */
private PlayerAuth preAuth() { private PlayerAuth preAuth() {
if (PlayerCache.getInstance().isAuthenticated(name)) { if (PlayerCache.getInstance().isAuthenticated(name)) {
m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR); service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
return null; return null;
} }
PlayerAuth pAuth = database.getAuth(name); PlayerAuth pAuth = database.getAuth(name);
if (pAuth == null) { if (pAuth == null) {
m.send(player, MessageKey.USER_NOT_REGISTERED); service.send(player, MessageKey.USER_NOT_REGISTERED);
if (LimboCache.getInstance().hasLimboPlayer(name)) {
LimboCache.getInstance().getLimboPlayer(name).getMessageTaskId().cancel(); LimboPlayer limboPlayer = LimboCache.getInstance().getLimboPlayer(name);
String[] msg; if (limboPlayer != null) {
if (Settings.emailRegistration) { limboPlayer.getMessageTask().cancel();
msg = m.retrieve(MessageKey.REGISTER_EMAIL_MESSAGE); String[] msg = service.getProperty(RegistrationSettings.USE_EMAIL_REGISTRATION)
} else { ? service.retrieveMessage(MessageKey.REGISTER_EMAIL_MESSAGE)
msg = m.retrieve(MessageKey.REGISTER_MESSAGE); : service.retrieveMessage(MessageKey.REGISTER_MESSAGE);
} BukkitTask messageTask = service.runTask(
BukkitTask msgT = Bukkit.getScheduler().runTask(plugin, new MessageTask(plugin, name, msg, service.getProperty(RegistrationSettings.MESSAGE_INTERVAL)));
new MessageTask(plugin, name, msg, settings.getProperty(RegistrationSettings.MESSAGE_INTERVAL))); limboPlayer.setMessageTask(messageTask);
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT);
} }
return null; return null;
} }
if (!Settings.getMySQLColumnGroup.isEmpty() && pAuth.getGroupId() == Settings.getNonActivatedGroup) { if (!service.getProperty(DatabaseSettings.MYSQL_COL_GROUP).isEmpty() && pAuth.getGroupId() == Settings.getNonActivatedGroup) {
m.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED); service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
return null; return null;
} }
@ -121,7 +112,7 @@ public class AsynchronousLogin {
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS) && !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& !ip.equalsIgnoreCase("127.0.0.1") && !ip.equalsIgnoreCase("localhost")) { && !ip.equalsIgnoreCase("127.0.0.1") && !ip.equalsIgnoreCase("localhost")) {
if (plugin.isLoggedIp(name, ip)) { if (plugin.isLoggedIp(name, ip)) {
m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR); service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
return null; return null;
} }
} }
@ -134,13 +125,14 @@ public class AsynchronousLogin {
return pAuth; return pAuth;
} }
public void process() { @Override
public void run() {
PlayerAuth pAuth = preAuth(); PlayerAuth pAuth = preAuth();
if (pAuth == null || needsCaptcha()) { if (pAuth == null || needsCaptcha()) {
return; return;
} }
if (pAuth.getIp().equals("127.0.0.1") && !pAuth.getIp().equals(ip)) { if ("127.0.0.1".equals(pAuth.getIp()) && !pAuth.getIp().equals(ip)) {
pAuth.setIp(ip); pAuth.setIp(ip);
database.updateIp(pAuth.getNickname(), ip); database.updateIp(pAuth.getNickname(), ip);
} }
@ -159,7 +151,7 @@ public class AsynchronousLogin {
.build(); .build();
database.updateSession(auth); database.updateSession(auth);
if (Settings.useCaptcha) { if (service.getProperty(SecuritySettings.USE_CAPTCHA)) {
if (plugin.captcha.containsKey(name)) { if (plugin.captcha.containsKey(name)) {
plugin.captcha.remove(name); plugin.captcha.remove(name);
} }
@ -170,12 +162,12 @@ public class AsynchronousLogin {
player.setNoDamageTicks(0); player.setNoDamageTicks(0);
if (!forceLogin) if (!forceLogin)
m.send(player, MessageKey.LOGIN_SUCCESS); service.send(player, MessageKey.LOGIN_SUCCESS);
displayOtherAccounts(auth); displayOtherAccounts(auth);
if (Settings.recallEmail && (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) { if (Settings.recallEmail && (StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email))) {
m.send(player, MessageKey.EMAIL_ADDED_SUCCESS); service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
} }
if (!Settings.noConsoleSpam) { if (!Settings.noConsoleSpam) {
@ -185,35 +177,35 @@ public class AsynchronousLogin {
// makes player isLoggedin via API // makes player isLoggedin via API
PlayerCache.getInstance().addPlayer(auth); PlayerCache.getInstance().addPlayer(auth);
database.setLogged(name); database.setLogged(name);
plugin.otherAccounts.addPlayer(player.getUniqueId());
// As the scheduling executes the Task most likely after the current // As the scheduling executes the Task most likely after the current
// task, we schedule it in the end // task, we schedule it in the end
// so that we can be sure, and have not to care if it might be // so that we can be sure, and have not to care if it might be
// processed in other order. // processed in other order.
ProcessSyncPlayerLogin syncPlayerLogin = new ProcessSyncPlayerLogin(player, plugin, database, settings); ProcessSyncPlayerLogin syncPlayerLogin = new ProcessSyncPlayerLogin(
player, plugin, database, service.getSettings());
if (syncPlayerLogin.getLimbo() != null) { if (syncPlayerLogin.getLimbo() != null) {
if (syncPlayerLogin.getLimbo().getTimeoutTaskId() != null) { if (syncPlayerLogin.getLimbo().getTimeoutTask() != null) {
syncPlayerLogin.getLimbo().getTimeoutTaskId().cancel(); syncPlayerLogin.getLimbo().getTimeoutTask().cancel();
} }
if (syncPlayerLogin.getLimbo().getMessageTaskId() != null) { if (syncPlayerLogin.getLimbo().getMessageTask() != null) {
syncPlayerLogin.getLimbo().getMessageTaskId().cancel(); syncPlayerLogin.getLimbo().getMessageTask().cancel();
} }
} }
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, syncPlayerLogin); Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, syncPlayerLogin);
} else if (player.isOnline()) { } else if (player.isOnline()) {
if (!Settings.noConsoleSpam) if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
ConsoleLogger.info(realName + " used the wrong password"); ConsoleLogger.info(realName + " used the wrong password");
if (Settings.isKickOnWrongPasswordEnabled) { }
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { if (service.getProperty(RestrictionSettings.KICK_ON_WRONG_PASSWORD)) {
service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
player.kickPlayer(m.retrieveSingle(MessageKey.WRONG_PASSWORD)); player.kickPlayer(service.retrieveSingleMessage(MessageKey.WRONG_PASSWORD));
} }
}); });
} else { } else {
m.send(player, MessageKey.WRONG_PASSWORD); service.send(player, MessageKey.WRONG_PASSWORD);
} }
} else { } else {
ConsoleLogger.showError("Player " + name + " wasn't online during login process, aborted... "); ConsoleLogger.showError("Player " + name + " wasn't online during login process, aborted... ");
@ -232,8 +224,8 @@ public class AsynchronousLogin {
String message = "[AuthMe] " + StringUtils.join(", ", auths) + "."; String message = "[AuthMe] " + StringUtils.join(", ", auths) + ".";
for (Player player : Utils.getOnlinePlayers()) { for (Player player : Utils.getOnlinePlayers()) {
if (plugin.getPermissionsManager().hasPermission(player, AdminPermission.SEE_OTHER_ACCOUNTS) if (plugin.getPermissionsManager().hasPermission(player, AdminPermission.SEE_OTHER_ACCOUNTS)
|| (player.getName().equals(this.player.getName()) || (player.getName().equals(this.player.getName())
&& plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) { && plugin.getPermissionsManager().hasPermission(player, PlayerPermission.SEE_OWN_ACCOUNTS))) {
player.sendMessage("[AuthMe] The player " + auth.getNickname() + " has " + auths.size() + " accounts"); player.sendMessage("[AuthMe] The player " + auth.getNickname() + " has " + auths.size() + " accounts");
player.sendMessage(message); player.sendMessage(message);
} }

View File

@ -38,7 +38,6 @@ public class ProcessSyncPlayerLogin implements Runnable {
private final String name; private final String name;
private final PlayerAuth auth; private final PlayerAuth auth;
private final AuthMe plugin; private final AuthMe plugin;
private final DataSource database;
private final PluginManager pm; private final PluginManager pm;
private final JsonCache playerCache; private final JsonCache playerCache;
private final NewSetting settings; private final NewSetting settings;
@ -54,7 +53,6 @@ public class ProcessSyncPlayerLogin implements Runnable {
public ProcessSyncPlayerLogin(Player player, AuthMe plugin, public ProcessSyncPlayerLogin(Player player, AuthMe plugin,
DataSource database, NewSetting settings) { DataSource database, NewSetting settings) {
this.plugin = plugin; this.plugin = plugin;
this.database = database;
this.pm = plugin.getServer().getPluginManager(); this.pm = plugin.getServer().getPluginManager();
this.player = player; this.player = player;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
@ -69,7 +67,7 @@ public class ProcessSyncPlayerLogin implements Runnable {
} }
private void restoreOpState() { private void restoreOpState() {
player.setOp(limbo.getOperator()); player.setOp(limbo.isOperator());
} }
private void packQuitLocation() { private void packQuitLocation() {

View File

@ -6,22 +6,22 @@ import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import fr.xephi.authme.util.Utils.GroupType; import fr.xephi.authme.util.Utils.GroupType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitScheduler;
/** /**
*/ */
public class AsynchronousLogout { public class AsynchronousLogout implements Process {
protected final Player player; private final Player player;
protected final String name; private final String name;
protected final AuthMe plugin; private final AuthMe plugin;
protected final DataSource database; private final DataSource database;
protected boolean canLogout = true; private boolean canLogout = true;
private final Messages m; private final ProcessService service;
/** /**
* Constructor for AsynchronousLogout. * Constructor for AsynchronousLogout.
@ -29,29 +29,30 @@ public class AsynchronousLogout {
* @param player Player * @param player Player
* @param plugin AuthMe * @param plugin AuthMe
* @param database DataSource * @param database DataSource
* @param service The process service
*/ */
public AsynchronousLogout(Player player, AuthMe plugin, DataSource database) { public AsynchronousLogout(Player player, AuthMe plugin, DataSource database, ProcessService service) {
this.m = plugin.getMessages();
this.player = player; this.player = player;
this.plugin = plugin; this.plugin = plugin;
this.database = database; this.database = database;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.service = service;
} }
private void preLogout() { private void preLogout() {
if (!PlayerCache.getInstance().isAuthenticated(name)) { if (!PlayerCache.getInstance().isAuthenticated(name)) {
m.send(player, MessageKey.NOT_LOGGED_IN); service.send(player, MessageKey.NOT_LOGGED_IN);
canLogout = false; canLogout = false;
} }
} }
public void process() { @Override
public void run() {
preLogout(); preLogout();
if (!canLogout) { if (!canLogout) {
return; return;
} }
final Player p = player; final Player p = player;
BukkitScheduler scheduler = p.getServer().getScheduler();
PlayerAuth auth = PlayerCache.getInstance().getAuth(name); PlayerAuth auth = PlayerCache.getInstance().getAuth(name);
database.updateSession(auth); database.updateSession(auth);
auth.setQuitLocX(p.getLocation().getX()); auth.setQuitLocX(p.getLocation().getX());
@ -62,7 +63,7 @@ public class AsynchronousLogout {
PlayerCache.getInstance().removePlayer(name); PlayerCache.getInstance().removePlayer(name);
database.setUnlogged(name); database.setUnlogged(name);
scheduler.scheduleSyncDelayedTask(plugin, new Runnable() { service.scheduleSyncDelayedTask(new Runnable() {
@Override @Override
public void run() { public void run() {
Utils.teleportToSpawn(p); Utils.teleportToSpawn(p);
@ -73,6 +74,6 @@ public class AsynchronousLogout {
} }
LimboCache.getInstance().addLimboPlayer(player); LimboCache.getInstance().addLimboPlayer(player);
Utils.setGroup(player, GroupType.NOTLOGGEDIN); Utils.setGroup(player, GroupType.NOTLOGGEDIN);
scheduler.scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerLogout(p, plugin)); service.scheduleSyncDelayedTask(new ProcessSynchronousPlayerLogout(p, plugin, service));
} }
} }

View File

@ -7,37 +7,40 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.events.LogoutEvent; import fr.xephi.authme.events.LogoutEvent;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
/** /**
*/ */
public class ProcessSyncronousPlayerLogout implements Runnable { public class ProcessSynchronousPlayerLogout implements Process {
protected final Player player; private final Player player;
protected final AuthMe plugin; private final AuthMe plugin;
protected final String name; private final String name;
private final Messages m; private final ProcessService service;
/** /**
* Constructor for ProcessSyncronousPlayerLogout. * Constructor for ProcessSynchronousPlayerLogout.
* *
* @param player Player * @param player Player
* @param plugin AuthMe * @param plugin AuthMe
* @param service The process service
*/ */
public ProcessSyncronousPlayerLogout(Player player, AuthMe plugin) { public ProcessSynchronousPlayerLogout(Player player, AuthMe plugin, ProcessService service) {
this.m = plugin.getMessages();
this.player = player; this.player = player;
this.plugin = plugin; this.plugin = plugin;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.service = service;
} }
protected void sendBungeeMessage() { protected void sendBungeeMessage() {
@ -56,11 +59,6 @@ public class ProcessSyncronousPlayerLogout implements Runnable {
} }
} }
/**
* Method run.
*
* @see java.lang.Runnable#run()
*/
@Override @Override
public void run() { public void run() {
if (plugin.sessions.containsKey(name)) { if (plugin.sessions.containsKey(name)) {
@ -70,19 +68,18 @@ public class ProcessSyncronousPlayerLogout implements Runnable {
if (Settings.protectInventoryBeforeLogInEnabled) { if (Settings.protectInventoryBeforeLogInEnabled) {
plugin.inventoryProtector.sendBlankInventoryPacket(player); plugin.inventoryProtector.sendBlankInventoryPacket(player);
} }
int timeOut = Settings.getRegistrationTimeout * 20; int timeOut = service.getProperty(RestrictionSettings.TIMEOUT) * 20;
int interval = Settings.getWarnMessageInterval; int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
BukkitScheduler sched = player.getServer().getScheduler();
if (timeOut != 0) { if (timeOut != 0) {
BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name, player), timeOut); BukkitTask id = service.runTaskLater(new TimeoutTask(plugin, name, player), timeOut);
LimboCache.getInstance().getLimboPlayer(name).setTimeoutTaskId(id); LimboCache.getInstance().getLimboPlayer(name).setTimeoutTask(id);
} }
BukkitTask msgT = sched.runTask(plugin, new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval)); BukkitTask msgT = service.runTask(new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
LimboCache.getInstance().getLimboPlayer(name).setMessageTaskId(msgT); LimboCache.getInstance().getLimboPlayer(name).setMessageTask(msgT);
if (player.isInsideVehicle() && player.getVehicle() != null) { if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject(); player.getVehicle().eject();
} }
if (Settings.applyBlindEffect) { if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2)); player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
} }
player.setOp(false); player.setOp(false);
@ -92,7 +89,7 @@ public class ProcessSyncronousPlayerLogout implements Runnable {
if (Settings.bungee) { if (Settings.bungee) {
sendBungeeMessage(); sendBungeeMessage();
} }
m.send(player, MessageKey.LOGOUT_SUCCESS); service.send(player, MessageKey.LOGOUT_SUCCESS);
ConsoleLogger.info(player.getName() + " logged out"); ConsoleLogger.info(player.getName() + " logged out");
} }

View File

@ -7,15 +7,17 @@ import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer; import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.datasource.CacheDataSource; import fr.xephi.authme.datasource.CacheDataSource;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
public class AsynchronousQuit { public class AsynchronousQuit implements Process {
private final AuthMe plugin; private final AuthMe plugin;
private final DataSource database; private final DataSource database;
@ -23,33 +25,40 @@ public class AsynchronousQuit {
private final String name; private final String name;
private boolean isOp = false; private boolean isOp = false;
private boolean needToChange = false; private boolean needToChange = false;
private boolean isKick = false; private final boolean isKick;
private final ProcessService service;
public AsynchronousQuit(Player p, AuthMe plugin, DataSource database, public AsynchronousQuit(Player p, AuthMe plugin, DataSource database, boolean isKick, ProcessService service) {
boolean isKick) {
this.player = p; this.player = p;
this.plugin = plugin; this.plugin = plugin;
this.database = database; this.database = database;
this.name = p.getName().toLowerCase(); this.name = p.getName().toLowerCase();
this.isKick = isKick; this.isKick = isKick;
this.service = service;
} }
public void process() { @Override
public void run() {
if (player == null || Utils.isUnrestricted(player)) { if (player == null || Utils.isUnrestricted(player)) {
return; return;
} }
String ip = plugin.getIP(player); String ip = service.getIpAddressManager().getPlayerIp(player);
if (PlayerCache.getInstance().isAuthenticated(name)) { if (PlayerCache.getInstance().isAuthenticated(name)) {
if (Settings.isSaveQuitLocationEnabled) { if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
Location loc = player.getLocation(); Location loc = player.getLocation();
PlayerAuth auth = PlayerAuth.builder() PlayerAuth auth = PlayerAuth.builder()
.name(name).location(loc) .name(name).location(loc)
.realName(player.getName()).build(); .realName(player.getName()).build();
database.updateQuitLoc(auth); database.updateQuitLoc(auth);
} }
PlayerAuth auth = new PlayerAuth(name, ip, System.currentTimeMillis(), player.getName()); PlayerAuth auth = PlayerAuth.builder()
.name(name)
.realName(player.getName())
.ip(ip)
.lastLogin(System.currentTimeMillis())
.build();
database.updateSession(auth); database.updateSession(auth);
} }
@ -59,7 +68,7 @@ public class AsynchronousQuit {
Utils.addNormal(player, limbo.getGroup()); Utils.addNormal(player, limbo.getGroup());
} }
needToChange = true; needToChange = true;
isOp = limbo.getOperator(); isOp = limbo.isOperator();
LimboCache.getInstance().deleteLimboPlayer(name); LimboCache.getInstance().deleteLimboPlayer(name);
} }
if (Settings.isSessionsEnabled && !isKick) { if (Settings.isSessionsEnabled && !isKick) {
@ -76,7 +85,7 @@ public class AsynchronousQuit {
plugin.sessions.put(name, task); plugin.sessions.put(name, task);
} else { } else {
//plugin is disable we canno schedule more tasks so run it directly here //plugin is disabled; we cannot schedule more tasks so run it directly here
postLogout(); postLogout();
} }
} }
@ -85,9 +94,9 @@ public class AsynchronousQuit {
database.setUnlogged(name); database.setUnlogged(name);
} }
plugin.realIp.remove(name); service.getIpAddressManager().removeCache(player.getName());
if (plugin.isEnabled()) { if (plugin.isEnabled()) {
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange)); service.scheduleSyncDelayedTask(new ProcessSyncronousPlayerQuit(plugin, player, isOp, needToChange));
} }
// remove player from cache // remove player from cache
if (database instanceof CacheDataSource) { if (database instanceof CacheDataSource) {

View File

@ -5,20 +5,23 @@ import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PlayerStatePermission; import fr.xephi.authme.permission.PlayerStatePermission;
import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.security.crypts.TwoFactor; import fr.xephi.authme.security.crypts.TwoFactor;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List;
/** /**
*/ */
public class AsyncRegister { public class AsyncRegister implements Process {
private final Player player; private final Player player;
private final String name; private final String name;
@ -27,65 +30,68 @@ public class AsyncRegister {
private final String email; private final String email;
private final AuthMe plugin; private final AuthMe plugin;
private final DataSource database; private final DataSource database;
private final Messages m; private final ProcessService service;
private final NewSetting settings;
public AsyncRegister(Player player, String password, String email, AuthMe plugin, DataSource data, public AsyncRegister(Player player, String password, String email, AuthMe plugin, DataSource data,
NewSetting settings) { ProcessService service) {
this.m = plugin.getMessages();
this.player = player; this.player = player;
this.password = password; this.password = password;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.email = email; this.email = email;
this.plugin = plugin; this.plugin = plugin;
this.database = data; this.database = data;
this.ip = plugin.getIP(player); this.ip = service.getIpAddressManager().getPlayerIp(player);
this.settings = settings; this.service = service;
} }
private boolean preRegisterCheck() { private boolean preRegisterCheck() {
String passLow = password.toLowerCase(); String passLow = password.toLowerCase();
if (PlayerCache.getInstance().isAuthenticated(name)) { if (PlayerCache.getInstance().isAuthenticated(name)) {
m.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR); service.send(player, MessageKey.ALREADY_LOGGED_IN_ERROR);
return false; return false;
} else if (!Settings.isRegistrationEnabled) { } else if (!Settings.isRegistrationEnabled) {
m.send(player, MessageKey.REGISTRATION_DISABLED); service.send(player, MessageKey.REGISTRATION_DISABLED);
return false; return false;
} }
//check the password safety only if it's not a automatically generated password //check the password safety only if it's not a automatically generated password
if (Settings.getPasswordHash != HashAlgorithm.TWO_FACTOR) { if (service.getProperty(SecuritySettings.PASSWORD_HASH) != HashAlgorithm.TWO_FACTOR) {
if (!passLow.matches(Settings.getPassRegex)) { if (!passLow.matches(Settings.getPassRegex)) {
m.send(player, MessageKey.PASSWORD_MATCH_ERROR); service.send(player, MessageKey.PASSWORD_MATCH_ERROR);
return false; return false;
} else if (passLow.equalsIgnoreCase(player.getName())) { } else if (passLow.equalsIgnoreCase(player.getName())) {
m.send(player, MessageKey.PASSWORD_IS_USERNAME_ERROR); service.send(player, MessageKey.PASSWORD_IS_USERNAME_ERROR);
return false; return false;
} else if (password.length() < Settings.getPasswordMinLen || password.length() > Settings.passwordMaxLength) { } else if (password.length() < Settings.getPasswordMinLen || password.length() > Settings.passwordMaxLength) {
m.send(player, MessageKey.INVALID_PASSWORD_LENGTH); service.send(player, MessageKey.INVALID_PASSWORD_LENGTH);
return false; return false;
} else if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(password.toLowerCase())) { } else if (!Settings.unsafePasswords.isEmpty() && Settings.unsafePasswords.contains(password.toLowerCase())) {
m.send(player, MessageKey.PASSWORD_UNSAFE_ERROR); service.send(player, MessageKey.PASSWORD_UNSAFE_ERROR);
return false; return false;
} }
} }
//check this in both possiblities so don't use 'else if' //check this in both possibilities so don't use 'else if'
if (database.isAuthAvailable(name)) { if (database.isAuthAvailable(name)) {
m.send(player, MessageKey.NAME_ALREADY_REGISTERED); service.send(player, MessageKey.NAME_ALREADY_REGISTERED);
return false; return false;
} else if (Settings.getmaxRegPerIp > 0 } else if(Settings.getmaxRegPerIp > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)
&& !ip.equalsIgnoreCase("127.0.0.1") && !ip.equalsIgnoreCase("127.0.0.1")
&& !ip.equalsIgnoreCase("localhost") && !ip.equalsIgnoreCase("localhost")
&& database.getAllAuthsByIp(ip).size() >= Settings.getmaxRegPerIp) { && !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED); int maxReg = Settings.getmaxRegPerIp;
return false; List<String> otherAccounts = database.getAllAuthsByIp(ip);
if (otherAccounts.size() >= maxReg) {
service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxReg),
Integer.toString(otherAccounts.size()), StringUtils.join(", ", otherAccounts.toString()));
return false;
}
} }
return true; return true;
} }
public void process() { @Override
public void run() {
if (preRegisterCheck()) { if (preRegisterCheck()) {
if (!StringUtils.isEmpty(email)) { if (!StringUtils.isEmpty(email)) {
emailRegister(); emailRegister();
@ -97,12 +103,17 @@ public class AsyncRegister {
private void emailRegister() { private void emailRegister() {
if (Settings.getmaxRegPerEmail > 0 if (Settings.getmaxRegPerEmail > 0
&& !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS) && !plugin.getPermissionsManager().hasPermission(player, PlayerStatePermission.ALLOW_MULTIPLE_ACCOUNTS)) {
&& database.countAuthsByEmail(email) >= Settings.getmaxRegPerEmail) { int maxReg = Settings.getmaxRegPerEmail;
m.send(player, MessageKey.MAX_REGISTER_EXCEEDED); int otherAccounts = database.countAuthsByEmail(email);
return; if (otherAccounts >= maxReg) {
service.send(player, MessageKey.MAX_REGISTER_EXCEEDED, Integer.toString(maxReg),
Integer.toString(otherAccounts), "@");
return;
}
} }
final HashedPassword hashedPassword = plugin.getPasswordSecurity().computeHash(password, name);
final HashedPassword hashedPassword = service.computeHash(password, name);
PlayerAuth auth = PlayerAuth.builder() PlayerAuth auth = PlayerAuth.builder()
.name(name) .name(name)
.realName(player.getName()) .realName(player.getName())
@ -113,19 +124,19 @@ public class AsyncRegister {
.build(); .build();
if (!database.saveAuth(auth)) { if (!database.saveAuth(auth)) {
m.send(player, MessageKey.ERROR); service.send(player, MessageKey.ERROR);
return; return;
} }
database.updateEmail(auth); database.updateEmail(auth);
database.updateSession(auth); database.updateSession(auth);
plugin.mail.main(auth, password); plugin.mail.main(auth, password);
ProcessSyncEmailRegister sync = new ProcessSyncEmailRegister(player, plugin); ProcessSyncEmailRegister sync = new ProcessSyncEmailRegister(player, service);
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, sync); service.scheduleSyncDelayedTask(sync);
} }
private void passwordRegister() { private void passwordRegister() {
final HashedPassword hashedPassword = plugin.getPasswordSecurity().computeHash(password, name); final HashedPassword hashedPassword = service.computeHash(password, name);
PlayerAuth auth = PlayerAuth.builder() PlayerAuth auth = PlayerAuth.builder()
.name(name) .name(name)
.realName(player.getName()) .realName(player.getName())
@ -135,7 +146,7 @@ public class AsyncRegister {
.build(); .build();
if (!database.saveAuth(auth)) { if (!database.saveAuth(auth)) {
m.send(player, MessageKey.ERROR); service.send(player, MessageKey.ERROR);
return; return;
} }
@ -146,14 +157,13 @@ public class AsyncRegister {
plugin.getManagement().performLogin(player, "dontneed", true); plugin.getManagement().performLogin(player, "dontneed", true);
} }
plugin.otherAccounts.addPlayer(player.getUniqueId()); ProcessSyncPasswordRegister sync = new ProcessSyncPasswordRegister(player, plugin, service);
ProcessSyncPasswordRegister sync = new ProcessSyncPasswordRegister(player, plugin, settings); service.scheduleSyncDelayedTask(sync);
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, sync);
//give the user the secret code to setup their app code generation //give the user the secret code to setup their app code generation
if (Settings.getPasswordHash == HashAlgorithm.TWO_FACTOR) { if (service.getProperty(SecuritySettings.PASSWORD_HASH) == HashAlgorithm.TWO_FACTOR) {
String qrCodeUrl = TwoFactor.getQRBarcodeURL(player.getName(), Bukkit.getIp(), hashedPassword.getHash()); String qrCodeUrl = TwoFactor.getQRBarcodeURL(player.getName(), Bukkit.getIp(), hashedPassword.getHash());
m.send(player, MessageKey.TWO_FACTOR_CREATE, hashedPassword.getHash(), qrCodeUrl); service.send(player, MessageKey.TWO_FACTOR_CREATE, hashedPassword.getHash(), qrCodeUrl);
} }
} }
} }

View File

@ -1,70 +1,64 @@
package fr.xephi.authme.process.register; package fr.xephi.authme.process.register;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer; import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
/** /**
*/ */
public class ProcessSyncEmailRegister implements Runnable { public class ProcessSyncEmailRegister implements Process {
protected final Player player; private final Player player;
protected final String name; private final String name;
private final AuthMe plugin; private final ProcessService service;
private final Messages m;
/** /**
* Constructor for ProcessSyncEmailRegister. * Constructor for ProcessSyncEmailRegister.
* *
* @param player Player * @param player The player to process an email registration for
* @param plugin AuthMe * @param service The process service
*/ */
public ProcessSyncEmailRegister(Player player, AuthMe plugin) { public ProcessSyncEmailRegister(Player player, ProcessService service) {
this.m = plugin.getMessages();
this.player = player; this.player = player;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.plugin = plugin; this.service = service;
} }
/**
* Method run.
*
* @see java.lang.Runnable#run()
*/
@Override @Override
public void run() { public void run() {
LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name); LimboPlayer limbo = LimboCache.getInstance().getLimboPlayer(name);
if (!Settings.getRegisteredGroup.isEmpty()) { if (!Settings.getRegisteredGroup.isEmpty()) {
Utils.setGroup(player, Utils.GroupType.REGISTERED); Utils.setGroup(player, Utils.GroupType.REGISTERED);
} }
m.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED); service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
int time = Settings.getRegistrationTimeout * 20; int time = service.getProperty(RestrictionSettings.TIMEOUT) * 20;
int msgInterval = Settings.getWarnMessageInterval; int msgInterval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
BukkitScheduler sched = plugin.getServer().getScheduler();
if (limbo != null) { if (limbo != null) {
if (time != 0) { if (time != 0) {
BukkitTask id = sched.runTaskLater(plugin, new TimeoutTask(plugin, name, player), time); BukkitTask id = service.runTaskLater(new TimeoutTask(service.getAuthMe(), name, player), time);
limbo.setTimeoutTaskId(id); limbo.setTimeoutTask(id);
} }
BukkitTask nwMsg = sched.runTask(plugin, new MessageTask(plugin, name, m.retrieve(MessageKey.LOGIN_MESSAGE), msgInterval)); BukkitTask messageTask = service.runTask(new MessageTask(
limbo.setMessageTaskId(nwMsg); service.getAuthMe(), name, service.retrieveMessage(MessageKey.LOGIN_MESSAGE), msgInterval));
limbo.setMessageTask(messageTask);
} }
player.saveData(); player.saveData();
if (!Settings.noConsoleSpam) { if (!service.getProperty(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE)) {
ConsoleLogger.info(player.getName() + " registered " + plugin.getIP(player)); ConsoleLogger.info(player.getName() + " registered " + service.getIpAddressManager().getPlayerIp(player));
} }
} }

View File

@ -9,42 +9,34 @@ import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.events.LoginEvent; import fr.xephi.authme.events.LoginEvent;
import fr.xephi.authme.events.RestoreInventoryEvent; import fr.xephi.authme.events.RestoreInventoryEvent;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Process;
import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.HooksSettings; import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
/** /**
*/ */
public class ProcessSyncPasswordRegister implements Runnable { public class ProcessSyncPasswordRegister implements Process {
protected final Player player; protected final Player player;
protected final String name; protected final String name;
private final AuthMe plugin; private final AuthMe plugin;
private final Messages m; private final ProcessService service;
private final NewSetting settings;
/** public ProcessSyncPasswordRegister(Player player, AuthMe plugin, ProcessService service) {
* Constructor for ProcessSyncPasswordRegister.
*
* @param player Player
* @param plugin AuthMe
* @param settings The plugin settings
*/
public ProcessSyncPasswordRegister(Player player, AuthMe plugin, NewSetting settings) {
this.m = plugin.getMessages();
this.player = player; this.player = player;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.plugin = plugin; this.plugin = plugin;
this.settings = settings; this.service = service;
} }
private void sendBungeeMessage() { private void sendBungeeMessage() {
@ -70,16 +62,15 @@ public class ProcessSyncPasswordRegister implements Runnable {
Utils.teleportToSpawn(player); Utils.teleportToSpawn(player);
LimboCache cache = LimboCache.getInstance(); LimboCache cache = LimboCache.getInstance();
cache.updateLimboPlayer(player); cache.updateLimboPlayer(player);
int delay = Settings.getRegistrationTimeout * 20; int delay = service.getProperty(RestrictionSettings.TIMEOUT) * 20;
int interval = Settings.getWarnMessageInterval; int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
BukkitScheduler sched = plugin.getServer().getScheduler();
BukkitTask task; BukkitTask task;
if (delay != 0) { if (delay != 0) {
task = sched.runTaskLater(plugin, new TimeoutTask(plugin, name, player), delay); task = service.runTaskLater(new TimeoutTask(service.getAuthMe(), name, player), delay);
cache.getLimboPlayer(name).setTimeoutTaskId(task); cache.getLimboPlayer(name).setTimeoutTask(task);
} }
task = sched.runTask(plugin, new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval)); task = service.runTask(new MessageTask(plugin, name, MessageKey.LOGIN_MESSAGE, interval));
cache.getLimboPlayer(name).setMessageTaskId(task); cache.getLimboPlayer(name).setMessageTask(task);
if (player.isInsideVehicle() && player.getVehicle() != null) { if (player.isInsideVehicle() && player.getVehicle() != null) {
player.getVehicle().eject(); player.getVehicle().eject();
} }
@ -106,13 +97,13 @@ public class ProcessSyncPasswordRegister implements Runnable {
Utils.setGroup(player, Utils.GroupType.REGISTERED); Utils.setGroup(player, Utils.GroupType.REGISTERED);
} }
m.send(player, MessageKey.REGISTER_SUCCESS); service.send(player, MessageKey.REGISTER_SUCCESS);
if (!Settings.getmailAccount.isEmpty()) { if (!Settings.getmailAccount.isEmpty()) {
m.send(player, MessageKey.ADD_EMAIL_MESSAGE); service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
} }
if (Settings.applyBlindEffect) { if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
player.removePotionEffect(PotionEffectType.BLINDNESS); player.removePotionEffect(PotionEffectType.BLINDNESS);
} }
@ -121,23 +112,23 @@ public class ProcessSyncPasswordRegister implements Runnable {
player.saveData(); player.saveData();
if (!Settings.noConsoleSpam) { if (!Settings.noConsoleSpam) {
ConsoleLogger.info(player.getName() + " registered " + plugin.getIP(player)); ConsoleLogger.info(player.getName() + " registered " + service.getIpAddressManager().getPlayerIp(player));
} }
// Kick Player after Registration is enabled, kick the player // Kick Player after Registration is enabled, kick the player
if (Settings.forceRegKick) { if (Settings.forceRegKick) {
player.kickPlayer(m.retrieveSingle(MessageKey.REGISTER_SUCCESS)); player.kickPlayer(service.retrieveSingleMessage(MessageKey.REGISTER_SUCCESS));
return; return;
} }
// Register is finish and player is logged, display welcome message // Register is finish and player is logged, display welcome message
if (Settings.useWelcomeMessage) { if (service.getProperty(RegistrationSettings.USE_WELCOME_MESSAGE)) {
if (Settings.broadcastWelcomeMessage) { if (service.getProperty(RegistrationSettings.BROADCAST_WELCOME_MESSAGE)) {
for (String s : settings.getWelcomeMessage()) { for (String s : service.getSettings().getWelcomeMessage()) {
plugin.getServer().broadcastMessage(plugin.replaceAllInfo(s, player)); plugin.getServer().broadcastMessage(plugin.replaceAllInfo(s, player));
} }
} else { } else {
for (String s : settings.getWelcomeMessage()) { for (String s : service.getSettings().getWelcomeMessage()) {
player.sendMessage(plugin.replaceAllInfo(s, player)); player.sendMessage(plugin.replaceAllInfo(s, player));
} }
} }
@ -160,10 +151,10 @@ public class ProcessSyncPasswordRegister implements Runnable {
} }
private void sendTo() { private void sendTo() {
if (!settings.getProperty(HooksSettings.BUNGEECORD_SERVER).isEmpty()) { if (!service.getProperty(HooksSettings.BUNGEECORD_SERVER).isEmpty()) {
ByteArrayDataOutput out = ByteStreams.newDataOutput(); ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("Connect"); out.writeUTF("Connect");
out.writeUTF(settings.getProperty(HooksSettings.BUNGEECORD_SERVER)); out.writeUTF(service.getProperty(HooksSettings.BUNGEECORD_SERVER));
player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray()); player.sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
} }
} }

View File

@ -8,8 +8,11 @@ import fr.xephi.authme.cache.backup.JsonCache;
import fr.xephi.authme.cache.limbo.LimboCache; import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer; import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages; import fr.xephi.authme.process.Process;
import fr.xephi.authme.process.ProcessService;
import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.task.MessageTask; import fr.xephi.authme.task.MessageTask;
import fr.xephi.authme.task.TimeoutTask; import fr.xephi.authme.task.TimeoutTask;
import fr.xephi.authme.util.Utils; import fr.xephi.authme.util.Utils;
@ -20,47 +23,46 @@ import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
public class AsynchronousUnregister { public class AsynchronousUnregister implements Process {
private final Player player; private final Player player;
private final String name; private final String name;
private final String password; private final String password;
private final boolean force; private final boolean force;
private final AuthMe plugin; private final AuthMe plugin;
private final Messages m;
private final JsonCache playerCache; private final JsonCache playerCache;
private final ProcessService service;
/** /**
* Constructor for AsynchronousUnregister. * Constructor.
* *
* @param player Player * @param player The player to perform the action for
* @param password String * @param password The password
* @param force boolean * @param force True to bypass password validation
* @param plugin AuthMe * @param plugin The plugin instance
* @param service The process service
*/ */
public AsynchronousUnregister(Player player, String password, boolean force, AuthMe plugin) { public AsynchronousUnregister(Player player, String password, boolean force, AuthMe plugin,
this.m = plugin.getMessages(); ProcessService service) {
this.player = player; this.player = player;
this.name = player.getName().toLowerCase(); this.name = player.getName().toLowerCase();
this.password = password; this.password = password;
this.force = force; this.force = force;
this.plugin = plugin; this.plugin = plugin;
this.playerCache = new JsonCache(); this.playerCache = new JsonCache();
this.service = service;
} }
protected String getIp() { @Override
return plugin.getIP(player); public void run() {
}
public void process() {
PlayerAuth cachedAuth = PlayerCache.getInstance().getAuth(name); PlayerAuth cachedAuth = PlayerCache.getInstance().getAuth(name);
if (force || plugin.getPasswordSecurity().comparePassword( if (force || plugin.getPasswordSecurity().comparePassword(
password, cachedAuth.getPassword(), player.getName())) { password, cachedAuth.getPassword(), player.getName())) {
if (!plugin.getDataSource().removeAuth(name)) { if (!service.getDataSource().removeAuth(name)) {
m.send(player, MessageKey.ERROR); service.send(player, MessageKey.ERROR);
return; return;
} }
int timeOut = Settings.getRegistrationTimeout * 20; int timeOut = service.getProperty(RestrictionSettings.TIMEOUT) * 20;
if (Settings.isForcedRegistrationEnabled) { if (Settings.isForcedRegistrationEnabled) {
Utils.teleportToSpawn(player); Utils.teleportToSpawn(player);
player.saveData(); player.saveData();
@ -70,15 +72,15 @@ public class AsynchronousUnregister {
} }
LimboCache.getInstance().addLimboPlayer(player); LimboCache.getInstance().addLimboPlayer(player);
LimboPlayer limboPlayer = LimboCache.getInstance().getLimboPlayer(name); LimboPlayer limboPlayer = LimboCache.getInstance().getLimboPlayer(name);
int interval = Settings.getWarnMessageInterval; int interval = service.getProperty(RegistrationSettings.MESSAGE_INTERVAL);
BukkitScheduler scheduler = plugin.getServer().getScheduler(); BukkitScheduler scheduler = plugin.getServer().getScheduler();
if (timeOut != 0) { if (timeOut != 0) {
BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, name, player), timeOut); BukkitTask id = scheduler.runTaskLater(plugin, new TimeoutTask(plugin, name, player), timeOut);
limboPlayer.setTimeoutTaskId(id); limboPlayer.setTimeoutTask(id);
} }
limboPlayer.setMessageTaskId(scheduler.runTask(plugin, limboPlayer.setMessageTask(scheduler.runTask(plugin,
new MessageTask(plugin, name, MessageKey.REGISTER_MESSAGE, interval))); new MessageTask(plugin, name, MessageKey.REGISTER_MESSAGE, interval)));
m.send(player, MessageKey.UNREGISTERED_SUCCESS); service.send(player, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(player.getDisplayName() + " unregistered himself"); ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
return; return;
} }
@ -92,14 +94,14 @@ public class AsynchronousUnregister {
playerCache.removeCache(player); playerCache.removeCache(player);
} }
// Apply blind effect // Apply blind effect
if (Settings.applyBlindEffect) { if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2)); player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeOut, 2));
} }
m.send(player, MessageKey.UNREGISTERED_SUCCESS); service.send(player, MessageKey.UNREGISTERED_SUCCESS);
ConsoleLogger.info(player.getDisplayName() + " unregistered himself"); ConsoleLogger.info(player.getDisplayName() + " unregistered himself");
Utils.teleportToSpawn(player); Utils.teleportToSpawn(player);
} else { } else {
m.send(player, MessageKey.WRONG_PASSWORD); service.send(player, MessageKey.WRONG_PASSWORD);
} }
} }
} }

View File

@ -4,6 +4,8 @@ import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.events.PasswordEncryptionEvent; import fr.xephi.authme.events.PasswordEncryptionEvent;
import fr.xephi.authme.security.crypts.EncryptionMethod; import fr.xephi.authme.security.crypts.EncryptionMethod;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.properties.SecuritySettings;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
/** /**
@ -11,17 +13,16 @@ import org.bukkit.plugin.PluginManager;
*/ */
public class PasswordSecurity { public class PasswordSecurity {
private HashAlgorithm algorithm;
private boolean supportOldAlgorithm;
private final DataSource dataSource; private final DataSource dataSource;
private final HashAlgorithm algorithm;
private final PluginManager pluginManager; private final PluginManager pluginManager;
private final boolean supportOldAlgorithm;
public PasswordSecurity(DataSource dataSource, HashAlgorithm algorithm, public PasswordSecurity(DataSource dataSource, NewSetting settings, PluginManager pluginManager) {
PluginManager pluginManager, boolean supportOldAlgorithm) { this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.supportOldAlgorithm = settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH);
this.dataSource = dataSource; this.dataSource = dataSource;
this.algorithm = algorithm;
this.pluginManager = pluginManager; this.pluginManager = pluginManager;
this.supportOldAlgorithm = supportOldAlgorithm;
} }
public HashedPassword computeHash(String password, String playerName) { public HashedPassword computeHash(String password, String playerName) {
@ -46,6 +47,11 @@ public class PasswordSecurity {
|| supportOldAlgorithm && compareWithAllEncryptionMethods(password, hashedPassword, playerLowerCase); || supportOldAlgorithm && compareWithAllEncryptionMethods(password, hashedPassword, playerLowerCase);
} }
public void reload(NewSetting settings) {
this.algorithm = settings.getProperty(SecuritySettings.PASSWORD_HASH);
this.supportOldAlgorithm = settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH);
}
/** /**
* Compare the given hash with all available encryption methods to support * Compare the given hash with all available encryption methods to support
* the migration to a new encryption method. Upon a successful match, the password * the migration to a new encryption method. Upon a successful match, the password

View File

@ -106,8 +106,9 @@ public class BinTools {
throw new IllegalArgumentException("Input string may only contain hex digits, but found '" + c + "'"); throw new IllegalArgumentException("Input string may only contain hex digits, but found '" + c + "'");
} }
// TODO ljacqu 20151219: Move to a BinToolsTest class // Note ljacqu 20160313: This appears to be a test method that was present in the third-party source.
private static void testUtils(String[] args) { // We can keep it for troubleshooting in the future.
private static void testUtils() {
byte b[] = new byte[256]; byte b[] = new byte[256];
byte bb = 0; byte bb = 0;
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {

View File

@ -1,94 +0,0 @@
package fr.xephi.authme.settings;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
/**
*/
public abstract class CustomConfiguration extends YamlConfiguration {
private final File configFile;
/**
* Constructor for CustomConfiguration.
*
* @param file the config file
*/
public CustomConfiguration(File file) {
this.configFile = file;
load();
}
public void load() {
try {
super.load(configFile);
} catch (FileNotFoundException e) {
ConsoleLogger.showError("Could not find " + configFile.getName() + ", creating new one...");
reLoad();
} catch (IOException e) {
ConsoleLogger.showError("Could not load " + configFile.getName());
} catch (InvalidConfigurationException e) {
ConsoleLogger.showError(configFile.getName() + " is no valid configuration file");
}
}
public boolean reLoad() {
boolean out = true;
if (!configFile.exists()) {
out = loadResource(configFile);
}
if (out)
load();
return out;
}
public void save() {
try {
super.save(configFile);
} catch (IOException ex) {
ConsoleLogger.showError("Could not save config to " + configFile.getName());
}
}
public File getConfigFile() {
return configFile;
}
private boolean loadResource(File file) {
if (!file.exists()) {
try {
if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
return false;
}
int i = file.getPath().indexOf("AuthMe");
if (i > -1) {
String path = file.getPath().substring(i + 6).replace('\\', '/');
InputStream is = AuthMe.class.getResourceAsStream(path);
Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
return true;
}
} catch (Exception e) {
ConsoleLogger.logException("Failed to load config from JAR", e);
}
}
return false;
}
public boolean containsAll(String... paths) {
for (String path : paths) {
if (!contains(path)) {
return false;
}
}
return true;
}
}

View File

@ -6,7 +6,6 @@ import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.domain.Property; import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.RegistrationSettings;
import fr.xephi.authme.settings.properties.SettingsFieldRetriever;
import fr.xephi.authme.settings.propertymap.PropertyMap; import fr.xephi.authme.settings.propertymap.PropertyMap;
import fr.xephi.authme.util.CollectionUtils; import fr.xephi.authme.util.CollectionUtils;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
@ -24,7 +23,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static fr.xephi.authme.settings.SettingsMigrationService.copyFileFromResource; import static fr.xephi.authme.util.FileUtils.copyFileFromResource;
/** /**
* The new settings manager. * The new settings manager.
@ -33,6 +32,8 @@ public class NewSetting {
private final File pluginFolder; private final File pluginFolder;
private final File configFile; private final File configFile;
private final PropertyMap propertyMap;
private final SettingsMigrationService migrationService;
private FileConfiguration configuration; private FileConfiguration configuration;
/** The file with the localized messages based on {@link PluginSettings#MESSAGES_LANGUAGE}. */ /** The file with the localized messages based on {@link PluginSettings#MESSAGES_LANGUAGE}. */
private File messagesFile; private File messagesFile;
@ -44,11 +45,16 @@ public class NewSetting {
* *
* @param configFile The configuration file * @param configFile The configuration file
* @param pluginFolder The AuthMe plugin folder * @param pluginFolder The AuthMe plugin folder
* @param propertyMap Collection of all available settings
* @param migrationService Migration service to check the settings file with
*/ */
public NewSetting(File configFile, File pluginFolder) { public NewSetting(File configFile, File pluginFolder, PropertyMap propertyMap,
SettingsMigrationService migrationService) {
this.configuration = YamlConfiguration.loadConfiguration(configFile); this.configuration = YamlConfiguration.loadConfiguration(configFile);
this.configFile = configFile; this.configFile = configFile;
this.pluginFolder = pluginFolder; this.pluginFolder = pluginFolder;
this.propertyMap = propertyMap;
this.migrationService = migrationService;
validateAndLoadOptions(); validateAndLoadOptions();
} }
@ -57,16 +63,21 @@ public class NewSetting {
* *
* @param configuration The FileConfiguration object to use * @param configuration The FileConfiguration object to use
* @param configFile The file to write to * @param configFile The file to write to
* @param pluginFolder The plugin folder
* @param propertyMap The property map whose properties should be verified for presence, or null to skip this * @param propertyMap The property map whose properties should be verified for presence, or null to skip this
* @param migrationService Migration service, or null to skip migration checks
*/ */
@VisibleForTesting @VisibleForTesting
NewSetting(FileConfiguration configuration, File configFile, PropertyMap propertyMap) { NewSetting(FileConfiguration configuration, File configFile, File pluginFolder, PropertyMap propertyMap,
SettingsMigrationService migrationService) {
this.configuration = configuration; this.configuration = configuration;
this.configFile = configFile; this.configFile = configFile;
this.pluginFolder = new File(""); this.pluginFolder = pluginFolder;
this.propertyMap = propertyMap;
this.migrationService = migrationService;
if (propertyMap != null && SettingsMigrationService.checkAndMigrate(configuration, propertyMap, pluginFolder)) { if (propertyMap != null && migrationService != null) {
save(propertyMap); validateAndLoadOptions();
} }
} }
@ -92,13 +103,6 @@ public class NewSetting {
configuration.set(property.getPath(), value); configuration.set(property.getPath(), value);
} }
/**
* Save the config file. Use after migrating one or more settings.
*/
public void save() {
save(SettingsFieldRetriever.getAllPropertyFields());
}
/** /**
* Return the messages file based on the messages language config. * Return the messages file based on the messages language config.
* *
@ -133,7 +137,10 @@ public class NewSetting {
validateAndLoadOptions(); validateAndLoadOptions();
} }
private void save(PropertyMap propertyMap) { /**
* Save the config file. Use after migrating one or more settings.
*/
public void save() {
try (FileWriter writer = new FileWriter(configFile)) { try (FileWriter writer = new FileWriter(configFile)) {
Yaml simpleYaml = newYaml(false); Yaml simpleYaml = newYaml(false);
Yaml singleQuoteYaml = newYaml(true); Yaml singleQuoteYaml = newYaml(true);
@ -186,11 +193,10 @@ public class NewSetting {
} }
private void validateAndLoadOptions() { private void validateAndLoadOptions() {
PropertyMap propertyMap = SettingsFieldRetriever.getAllPropertyFields(); if (migrationService.checkAndMigrate(configuration, propertyMap, pluginFolder)) {
if (SettingsMigrationService.checkAndMigrate(configuration, propertyMap, pluginFolder)) {
ConsoleLogger.info("Merged new config options"); ConsoleLogger.info("Merged new config options");
ConsoleLogger.info("Please check your config.yml file for new settings!"); ConsoleLogger.info("Please check your config.yml file for new settings!");
save(propertyMap); save();
} }
messagesFile = buildMessagesFile(); messagesFile = buildMessagesFile();
@ -205,18 +211,20 @@ public class NewSetting {
private File buildMessagesFile() { private File buildMessagesFile() {
String languageCode = getProperty(PluginSettings.MESSAGES_LANGUAGE); String languageCode = getProperty(PluginSettings.MESSAGES_LANGUAGE);
File messagesFile = buildMessagesFileFromCode(languageCode);
if (messagesFile.exists()) { String filePath = buildMessagesFilePathFromCode(languageCode);
File messagesFile = new File(pluginFolder, filePath);
if (copyFileFromResource(messagesFile, filePath)) {
return messagesFile; return messagesFile;
} }
return copyFileFromResource(messagesFile, buildMessagesFilePathFromCode(languageCode)) // File doesn't exist or couldn't be copied - try again with default, "en"
? messagesFile String defaultFilePath = buildMessagesFilePathFromCode("en");
: buildMessagesFileFromCode("en"); File defaultFile = new File(pluginFolder, defaultFilePath);
} copyFileFromResource(defaultFile, defaultFilePath);
private File buildMessagesFileFromCode(String language) { // No matter the result, need to return a file
return new File(pluginFolder, buildMessagesFilePathFromCode(language)); return defaultFile;
} }
private static String buildMessagesFilePathFromCode(String language) { private static String buildMessagesFilePathFromCode(String language) {
@ -243,7 +251,7 @@ public class NewSetting {
final Charset charset = Charset.forName("UTF-8"); final Charset charset = Charset.forName("UTF-8");
if (copyFileFromResource(emailFile, "email.html")) { if (copyFileFromResource(emailFile, "email.html")) {
try { try {
return StringUtils.join("", Files.readLines(emailFile, charset)); return StringUtils.join("\n", Files.readLines(emailFile, charset));
} catch (IOException e) { } catch (IOException e) {
ConsoleLogger.logException("Failed to read file '" + emailFile.getPath() + "':", e); ConsoleLogger.logException("Failed to read file '" + emailFile.getPath() + "':", e);
} }

View File

@ -1,96 +0,0 @@
package fr.xephi.authme.settings;
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 $
*/
public class OtherAccounts extends CustomConfiguration {
private static OtherAccounts others = null;
public OtherAccounts() {
super(new File("." + File.separator + "plugins" + File.separator + "AuthMe" + File.separator + "otheraccounts.yml"));
others = this;
load();
save();
}
/**
* Method getInstance.
*
* @return OtherAccounts
*/
public static OtherAccounts getInstance() {
if (others == null) {
others = new OtherAccounts();
}
return others;
}
/**
* Method clear.
*
* @param uuid UUID
*/
public void clear(UUID uuid) {
set(uuid.toString(), new ArrayList<String>());
save();
}
/**
* Method addPlayer.
*
* @param uuid UUID
*/
public void addPlayer(UUID uuid) {
try {
Player player = Bukkit.getPlayer(uuid);
if (player == null)
return;
if (!this.getStringList(uuid.toString()).contains(player.getName())) {
this.getStringList(uuid.toString()).add(player.getName());
save();
}
} catch (NoSuchMethodError | Exception e) {
//ignore
}
}
/**
* Method removePlayer.
*
* @param uuid UUID
*/
public void removePlayer(UUID uuid) {
try {
Player player = Bukkit.getPlayer(uuid);
if (player == null)
return;
if (this.getStringList(uuid.toString()).contains(player.getName())) {
this.getStringList(uuid.toString()).remove(player.getName());
save();
}
} catch (NoSuchMethodError | Exception e) {
//ignore
}
}
/**
* Method getAllPlayersByUUID.
*
* @param uuid UUID
*
* @return StringList
*/
public List<String> getAllPlayersByUUID(UUID uuid) {
return this.getStringList(uuid.toString());
}
}

View File

@ -1,10 +1,8 @@
package fr.xephi.authme.settings; package fr.xephi.authme.settings;
import fr.xephi.authme.AuthMe; import fr.xephi.authme.AuthMe;
import fr.xephi.authme.datasource.DataSourceType;
import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.domain.Property; import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.properties.DatabaseSettings;
import fr.xephi.authme.settings.properties.HooksSettings; import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.RegistrationSettings;
@ -41,13 +39,9 @@ public final class Settings {
public static List<String> forceRegisterCommands; public static List<String> forceRegisterCommands;
public static List<String> forceRegisterCommandsAsConsole; public static List<String> forceRegisterCommandsAsConsole;
public static List<String> unsafePasswords; public static List<String> unsafePasswords;
public static List<String> emailBlacklist;
public static List<String> emailWhitelist;
public static DataSourceType getDataSource;
public static HashAlgorithm getPasswordHash; public static HashAlgorithm getPasswordHash;
public static Pattern nickPattern; public static Pattern nickPattern;
public static boolean useLogging = false; public static boolean useLogging = false;
public static int purgeDelay = 60;
public static boolean isChatAllowed, isPermissionCheckEnabled, isRegistrationEnabled, public static boolean isChatAllowed, isPermissionCheckEnabled, isRegistrationEnabled,
isForcedRegistrationEnabled, isTeleportToSpawnEnabled, isForcedRegistrationEnabled, isTeleportToSpawnEnabled,
isSessionsEnabled, isAllowRestrictedIp, isSessionsEnabled, isAllowRestrictedIp,
@ -57,34 +51,27 @@ public final class Settings {
isKickOnWrongPasswordEnabled, enablePasswordConfirmation, isKickOnWrongPasswordEnabled, enablePasswordConfirmation,
protectInventoryBeforeLogInEnabled, isStopEnabled, reloadSupport, protectInventoryBeforeLogInEnabled, isStopEnabled, reloadSupport,
rakamakUseIp, noConsoleSpam, removePassword, displayOtherAccounts, rakamakUseIp, noConsoleSpam, removePassword, displayOtherAccounts,
useCaptcha, emailRegistration, multiverse, bungee, emailRegistration, multiverse, bungee,
banUnsafeIp, doubleEmailCheck, sessionExpireOnIpChange, banUnsafeIp, doubleEmailCheck, sessionExpireOnIpChange,
disableSocialSpy, useEssentialsMotd, usePurge, disableSocialSpy, useEssentialsMotd,
purgePlayerDat, purgeEssentialsFile, supportOldPassword, enableProtection, recallEmail, useWelcomeMessage,
purgeLimitedCreative, purgeAntiXray, purgePermissions,
enableProtection, enableAntiBot, recallEmail, useWelcomeMessage,
broadcastWelcomeMessage, forceRegKick, forceRegLogin, broadcastWelcomeMessage, forceRegKick, forceRegLogin,
checkVeryGames, removeJoinMessage, removeLeaveMessage, delayJoinMessage, checkVeryGames, removeJoinMessage, removeLeaveMessage, delayJoinMessage,
noTeleport, applyBlindEffect, hideTablistBeforeLogin, denyTabcompleteBeforeLogin, noTeleport, hideTablistBeforeLogin, denyTabcompleteBeforeLogin,
kickPlayersBeforeStopping, allowAllCommandsIfRegIsOptional, kickPlayersBeforeStopping, allowAllCommandsIfRegIsOptional,
customAttributes, generateImage, isRemoveSpeedEnabled, preventOtherCase; customAttributes, isRemoveSpeedEnabled, preventOtherCase;
public static String getNickRegex, getUnloggedinGroup, public static String getNickRegex, getUnloggedinGroup,
getMySQLColumnGroup, unRegisteredGroup, unRegisteredGroup,
backupWindowsPath, getRegisteredGroup, backupWindowsPath, getRegisteredGroup,
rakamakUsers, rakamakUsersIp, getmailAccount, defaultWorld, rakamakUsers, rakamakUsersIp, getmailAccount, defaultWorld,
getPhpbbPrefix, getWordPressPrefix,
spawnPriority, crazyloginFileName, getPassRegex, sendPlayerTo; spawnPriority, crazyloginFileName, getPassRegex, sendPlayerTo;
public static int getWarnMessageInterval, getSessionTimeout, public static int getWarnMessageInterval, getSessionTimeout,
getRegistrationTimeout, getMaxNickLength, getMinNickLength, getRegistrationTimeout, getMaxNickLength, getMinNickLength,
getPasswordMinLen, getMovementRadius, getmaxRegPerIp, getPasswordMinLen, getMovementRadius, getmaxRegPerIp,
getNonActivatedGroup, passwordMaxLength, getRecoveryPassLength, getNonActivatedGroup, passwordMaxLength, getRecoveryPassLength,
getMailPort, maxLoginTry, captchaLength, saltLength, getMailPort, maxLoginTry, captchaLength, saltLength,
getmaxRegPerEmail, bCryptLog2Rounds, getPhpbbGroup, getmaxRegPerEmail, bCryptLog2Rounds, getMaxLoginPerIp, getMaxJoinPerIp;
antiBotSensibility, antiBotDuration, delayRecall, getMaxLoginPerIp,
getMaxJoinPerIp;
protected static FileConfiguration configFile; protected static FileConfiguration configFile;
private static AuthMe plugin;
private static Settings instance;
/** /**
* Constructor for Settings. * Constructor for Settings.
@ -92,29 +79,27 @@ public final class Settings {
* @param pl AuthMe * @param pl AuthMe
*/ */
public Settings(AuthMe pl) { public Settings(AuthMe pl) {
instance = this; configFile = pl.getConfig();
plugin = pl;
configFile = plugin.getConfig();
loadVariables(); loadVariables();
} }
public static void loadVariables() { private static void loadVariables() {
isPermissionCheckEnabled = load(PluginSettings.ENABLE_PERMISSION_CHECK); isPermissionCheckEnabled = load(PluginSettings.ENABLE_PERMISSION_CHECK);
isForcedRegistrationEnabled = configFile.getBoolean("settings.registration.force", true); isForcedRegistrationEnabled = configFile.getBoolean("settings.registration.force", true);
isRegistrationEnabled = configFile.getBoolean("settings.registration.enabled", true); isRegistrationEnabled = configFile.getBoolean("settings.registration.enabled", true);
isTeleportToSpawnEnabled = configFile.getBoolean("settings.restrictions.teleportUnAuthedToSpawn", false); isTeleportToSpawnEnabled = load(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN);
getWarnMessageInterval = configFile.getInt("settings.registration.messageInterval", 5); getWarnMessageInterval = load(RegistrationSettings.MESSAGE_INTERVAL);
isSessionsEnabled = configFile.getBoolean("settings.sessions.enabled", false); isSessionsEnabled = load(PluginSettings.SESSIONS_ENABLED);
getSessionTimeout = configFile.getInt("settings.sessions.timeout", 10); getSessionTimeout = configFile.getInt("settings.sessions.timeout", 10);
getRegistrationTimeout = configFile.getInt("settings.restrictions.timeout", 30); getRegistrationTimeout = load(RestrictionSettings.TIMEOUT);
isChatAllowed = configFile.getBoolean("settings.restrictions.allowChat", false); isChatAllowed = load(RestrictionSettings.ALLOW_CHAT);
getMaxNickLength = configFile.getInt("settings.restrictions.maxNicknameLength", 20); getMaxNickLength = configFile.getInt("settings.restrictions.maxNicknameLength", 20);
getMinNickLength = configFile.getInt("settings.restrictions.minNicknameLength", 3); getMinNickLength = configFile.getInt("settings.restrictions.minNicknameLength", 3);
getPasswordMinLen = configFile.getInt("settings.security.minPasswordLength", 4); getPasswordMinLen = configFile.getInt("settings.security.minPasswordLength", 4);
getNickRegex = configFile.getString("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_?]*"); getNickRegex = configFile.getString("settings.restrictions.allowedNicknameCharacters", "[a-zA-Z0-9_?]*");
nickPattern = Pattern.compile(getNickRegex); nickPattern = Pattern.compile(getNickRegex);
isAllowRestrictedIp = configFile.getBoolean("settings.restrictions.AllowRestrictedUser", false); isAllowRestrictedIp = load(RestrictionSettings.ENABLE_RESTRICTED_USERS);
getRestrictedIp = configFile.getStringList("settings.restrictions.AllowedRestrictedUser"); getRestrictedIp = load(RestrictionSettings.ALLOWED_RESTRICTED_USERS);
isMovementAllowed = configFile.getBoolean("settings.restrictions.allowMovement", false); isMovementAllowed = configFile.getBoolean("settings.restrictions.allowMovement", false);
isRemoveSpeedEnabled = configFile.getBoolean("settings.restrictions.removeSpeed", true); isRemoveSpeedEnabled = configFile.getBoolean("settings.restrictions.removeSpeed", true);
getMovementRadius = configFile.getInt("settings.restrictions.allowedMovementRadius", 100); getMovementRadius = configFile.getInt("settings.restrictions.allowedMovementRadius", 100);
@ -128,8 +113,6 @@ public final class Settings {
getmaxRegPerIp = configFile.getInt("settings.restrictions.maxRegPerIp", 1); getmaxRegPerIp = configFile.getInt("settings.restrictions.maxRegPerIp", 1);
getPasswordHash = load(SecuritySettings.PASSWORD_HASH); getPasswordHash = load(SecuritySettings.PASSWORD_HASH);
getUnloggedinGroup = load(SecuritySettings.UNLOGGEDIN_GROUP); getUnloggedinGroup = load(SecuritySettings.UNLOGGEDIN_GROUP);
getDataSource = load(DatabaseSettings.BACKEND);
getMySQLColumnGroup = configFile.getString("ExternalBoardOptions.mySQLColumnGroup", "");
getNonActivatedGroup = configFile.getInt("ExternalBoardOptions.nonActivedUserGroup", -1); getNonActivatedGroup = configFile.getInt("ExternalBoardOptions.nonActivedUserGroup", -1);
unRegisteredGroup = configFile.getString("GroupOptions.UnregisteredPlayerGroup", ""); unRegisteredGroup = configFile.getString("GroupOptions.UnregisteredPlayerGroup", "");
@ -163,16 +146,15 @@ public final class Settings {
rakamakUsers = configFile.getString("Converter.Rakamak.fileName", "users.rak"); rakamakUsers = configFile.getString("Converter.Rakamak.fileName", "users.rak");
rakamakUsersIp = configFile.getString("Converter.Rakamak.ipFileName", "UsersIp.rak"); rakamakUsersIp = configFile.getString("Converter.Rakamak.ipFileName", "UsersIp.rak");
rakamakUseIp = configFile.getBoolean("Converter.Rakamak.useIp", false); rakamakUseIp = configFile.getBoolean("Converter.Rakamak.useIp", false);
noConsoleSpam = configFile.getBoolean("Security.console.noConsoleSpam", false); noConsoleSpam = load(SecuritySettings.REMOVE_SPAM_FROM_CONSOLE);
removePassword = configFile.getBoolean("Security.console.removePassword", true); removePassword = configFile.getBoolean("Security.console.removePassword", true);
getmailAccount = configFile.getString("Email.mailAccount", ""); getmailAccount = configFile.getString("Email.mailAccount", "");
getMailPort = configFile.getInt("Email.mailPort", 465); getMailPort = configFile.getInt("Email.mailPort", 465);
getRecoveryPassLength = configFile.getInt("Email.RecoveryPasswordLength", 8); getRecoveryPassLength = configFile.getInt("Email.RecoveryPasswordLength", 8);
displayOtherAccounts = configFile.getBoolean("settings.restrictions.displayOtherAccounts", true); displayOtherAccounts = configFile.getBoolean("settings.restrictions.displayOtherAccounts", true);
useCaptcha = configFile.getBoolean("Security.captcha.useCaptcha", false);
maxLoginTry = configFile.getInt("Security.captcha.maxLoginTry", 5); maxLoginTry = configFile.getInt("Security.captcha.maxLoginTry", 5);
captchaLength = configFile.getInt("Security.captcha.captchaLength", 5); captchaLength = configFile.getInt("Security.captcha.captchaLength", 5);
emailRegistration = configFile.getBoolean("settings.registration.enableEmailRegistrationSystem", false); emailRegistration = load(RegistrationSettings.USE_EMAIL_REGISTRATION);
saltLength = configFile.getInt("settings.security.doubleMD5SaltLength", 8); saltLength = configFile.getInt("settings.security.doubleMD5SaltLength", 8);
getmaxRegPerEmail = configFile.getInt("Email.maxRegPerEmail", 1); getmaxRegPerEmail = configFile.getInt("Email.maxRegPerEmail", 1);
multiverse = load(HooksSettings.MULTIVERSE); multiverse = load(HooksSettings.MULTIVERSE);
@ -185,50 +167,31 @@ public final class Settings {
disableSocialSpy = configFile.getBoolean("Hooks.disableSocialSpy", true); disableSocialSpy = configFile.getBoolean("Hooks.disableSocialSpy", true);
bCryptLog2Rounds = configFile.getInt("ExternalBoardOptions.bCryptLog2Round", 10); bCryptLog2Rounds = configFile.getInt("ExternalBoardOptions.bCryptLog2Round", 10);
useEssentialsMotd = configFile.getBoolean("Hooks.useEssentialsMotd", false); useEssentialsMotd = configFile.getBoolean("Hooks.useEssentialsMotd", false);
usePurge = configFile.getBoolean("Purge.useAutoPurge", false);
purgeDelay = configFile.getInt("Purge.daysBeforeRemovePlayer", 60);
purgePlayerDat = configFile.getBoolean("Purge.removePlayerDat", false);
purgeEssentialsFile = configFile.getBoolean("Purge.removeEssentialsFile", false);
defaultWorld = configFile.getString("Purge.defaultWorld", "world"); defaultWorld = configFile.getString("Purge.defaultWorld", "world");
getPhpbbPrefix = configFile.getString("ExternalBoardOptions.phpbbTablePrefix", "phpbb_");
getPhpbbGroup = configFile.getInt("ExternalBoardOptions.phpbbActivatedGroupId", 2);
supportOldPassword = configFile.getBoolean("settings.security.supportOldPasswordHash", false);
getWordPressPrefix = configFile.getString("ExternalBoardOptions.wordpressTablePrefix", "wp_");
purgeLimitedCreative = configFile.getBoolean("Purge.removeLimitedCreativesInventories", false);
purgeAntiXray = configFile.getBoolean("Purge.removeAntiXRayFile", false);
purgePermissions = configFile.getBoolean("Purge.removePermissions", false);
enableProtection = configFile.getBoolean("Protection.enableProtection", false); enableProtection = configFile.getBoolean("Protection.enableProtection", false);
countries = configFile.getStringList("Protection.countries"); countries = configFile.getStringList("Protection.countries");
enableAntiBot = configFile.getBoolean("Protection.enableAntiBot", false);
antiBotSensibility = configFile.getInt("Protection.antiBotSensibility", 5);
antiBotDuration = configFile.getInt("Protection.antiBotDuration", 10);
forceCommands = configFile.getStringList("settings.forceCommands"); forceCommands = configFile.getStringList("settings.forceCommands");
forceCommandsAsConsole = configFile.getStringList("settings.forceCommandsAsConsole"); forceCommandsAsConsole = configFile.getStringList("settings.forceCommandsAsConsole");
recallEmail = configFile.getBoolean("Email.recallPlayers", false); recallEmail = configFile.getBoolean("Email.recallPlayers", false);
delayRecall = configFile.getInt("Email.delayRecall", 5); useWelcomeMessage = load(RegistrationSettings.USE_WELCOME_MESSAGE);
useWelcomeMessage = configFile.getBoolean("settings.useWelcomeMessage", true);
unsafePasswords = configFile.getStringList("settings.security.unsafePasswords"); unsafePasswords = configFile.getStringList("settings.security.unsafePasswords");
countriesBlacklist = configFile.getStringList("Protection.countriesBlacklist"); countriesBlacklist = configFile.getStringList("Protection.countriesBlacklist");
broadcastWelcomeMessage = configFile.getBoolean("settings.broadcastWelcomeMessage", false); broadcastWelcomeMessage = load(RegistrationSettings.BROADCAST_WELCOME_MESSAGE);
forceRegKick = configFile.getBoolean("settings.registration.forceKickAfterRegister", false); forceRegKick = configFile.getBoolean("settings.registration.forceKickAfterRegister", false);
forceRegLogin = configFile.getBoolean("settings.registration.forceLoginAfterRegister", false); forceRegLogin = load(RegistrationSettings.FORCE_LOGIN_AFTER_REGISTER);
spawnPriority = load(RestrictionSettings.SPAWN_PRIORITY); spawnPriority = load(RestrictionSettings.SPAWN_PRIORITY);
getMaxLoginPerIp = configFile.getInt("settings.restrictions.maxLoginPerIp", 0); getMaxLoginPerIp = load(RestrictionSettings.MAX_LOGIN_PER_IP);
getMaxJoinPerIp = configFile.getInt("settings.restrictions.maxJoinPerIp", 0); getMaxJoinPerIp = load(RestrictionSettings.MAX_JOIN_PER_IP);
checkVeryGames = configFile.getBoolean("VeryGames.enableIpCheck", false); checkVeryGames = load(HooksSettings.ENABLE_VERYGAMES_IP_CHECK);
removeJoinMessage = load(RegistrationSettings.REMOVE_JOIN_MESSAGE); removeJoinMessage = load(RegistrationSettings.REMOVE_JOIN_MESSAGE);
removeLeaveMessage = load(RegistrationSettings.REMOVE_LEAVE_MESSAGE); removeLeaveMessage = load(RegistrationSettings.REMOVE_LEAVE_MESSAGE);
delayJoinMessage = load(RegistrationSettings.DELAY_JOIN_MESSAGE); delayJoinMessage = load(RegistrationSettings.DELAY_JOIN_MESSAGE);
noTeleport = configFile.getBoolean("settings.restrictions.noTeleport", false); noTeleport = load(RestrictionSettings.NO_TELEPORT);
crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db"); crazyloginFileName = configFile.getString("Converter.CrazyLogin.fileName", "accounts.db");
getPassRegex = configFile.getString("settings.restrictions.allowedPasswordCharacters", "[\\x21-\\x7E]*"); getPassRegex = configFile.getString("settings.restrictions.allowedPasswordCharacters", "[\\x21-\\x7E]*");
applyBlindEffect = configFile.getBoolean("settings.applyBlindEffect", false);
emailBlacklist = configFile.getStringList("Email.emailBlacklisted");
emailWhitelist = configFile.getStringList("Email.emailWhitelisted");
forceRegisterCommands = configFile.getStringList("settings.forceRegisterCommands"); forceRegisterCommands = configFile.getStringList("settings.forceRegisterCommands");
forceRegisterCommandsAsConsole = configFile.getStringList("settings.forceRegisterCommandsAsConsole"); forceRegisterCommandsAsConsole = configFile.getStringList("settings.forceRegisterCommandsAsConsole");
customAttributes = configFile.getBoolean("Hooks.customAttributes"); customAttributes = configFile.getBoolean("Hooks.customAttributes");
generateImage = configFile.getBoolean("Email.generateImage", false);
preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false); preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false);
kickPlayersBeforeStopping = configFile.getBoolean("Security.stop.kickPlayersBeforeStopping", true); kickPlayersBeforeStopping = configFile.getBoolean("Security.stop.kickPlayersBeforeStopping", true);
sendPlayerTo = configFile.getString("Hooks.sendPlayerTo", ""); sendPlayerTo = configFile.getString("Hooks.sendPlayerTo", "");

View File

@ -1,7 +1,5 @@
package fr.xephi.authme.settings; package fr.xephi.authme.settings;
import com.google.common.annotations.VisibleForTesting;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.settings.domain.Property; import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.propertymap.PropertyMap; import fr.xephi.authme.settings.propertymap.PropertyMap;
@ -10,37 +8,32 @@ import org.bukkit.configuration.file.FileConfiguration;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import static fr.xephi.authme.settings.properties.RegistrationSettings.DELAY_JOIN_MESSAGE; import static fr.xephi.authme.settings.properties.RegistrationSettings.DELAY_JOIN_MESSAGE;
import static fr.xephi.authme.settings.properties.RegistrationSettings.REMOVE_JOIN_MESSAGE; import static fr.xephi.authme.settings.properties.RegistrationSettings.REMOVE_JOIN_MESSAGE;
import static fr.xephi.authme.settings.properties.RegistrationSettings.REMOVE_LEAVE_MESSAGE; import static fr.xephi.authme.settings.properties.RegistrationSettings.REMOVE_LEAVE_MESSAGE;
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_NICKNAME_CHARACTERS; import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_NICKNAME_CHARACTERS;
import static java.lang.String.format;
/** /**
* Service for verifying that the configuration is up-to-date. * Service for verifying that the configuration is up-to-date.
*/ */
public final class SettingsMigrationService { public class SettingsMigrationService {
private SettingsMigrationService() {
}
/** /**
* Checks the config file and does any necessary migrations. * Checks the config file and performs any necessary migrations.
* *
* @param configuration The file configuration to check and migrate * @param configuration The file configuration to check and migrate
* @param propertyMap The property map of all existing properties * @param propertyMap The property map of all existing properties
* @param pluginFolder The plugin folder * @param pluginFolder The plugin folder
* @return True if there is a change and the config must be saved, false if the config is up-to-date * @return True if there is a change and the config must be saved, false if the config is up-to-date
*/ */
public static boolean checkAndMigrate(FileConfiguration configuration, PropertyMap propertyMap, File pluginFolder) { public boolean checkAndMigrate(FileConfiguration configuration, PropertyMap propertyMap, File pluginFolder) {
return performMigrations(configuration, pluginFolder) || hasDeprecatedProperties(configuration) return performMigrations(configuration, pluginFolder)
|| hasDeprecatedProperties(configuration)
|| !containsAllSettings(configuration, propertyMap); || !containsAllSettings(configuration, propertyMap);
} }
private static boolean performMigrations(FileConfiguration configuration, File pluginFolder) { private boolean performMigrations(FileConfiguration configuration, File pluginFolder) {
boolean changes = false; boolean changes = false;
if ("[a-zA-Z0-9_?]*".equals(configuration.getString(ALLOWED_NICKNAME_CHARACTERS.getPath()))) { if ("[a-zA-Z0-9_?]*".equals(configuration.getString(ALLOWED_NICKNAME_CHARACTERS.getPath()))) {
configuration.set(ALLOWED_NICKNAME_CHARACTERS.getPath(), "[a-zA-Z0-9_]*"); configuration.set(ALLOWED_NICKNAME_CHARACTERS.getPath(), "[a-zA-Z0-9_]*");
@ -54,8 +47,7 @@ public final class SettingsMigrationService {
| migrateJoinLeaveMessages(configuration); | migrateJoinLeaveMessages(configuration);
} }
@VisibleForTesting public boolean containsAllSettings(FileConfiguration configuration, PropertyMap propertyMap) {
static boolean containsAllSettings(FileConfiguration configuration, PropertyMap propertyMap) {
for (Property<?> property : propertyMap.keySet()) { for (Property<?> property : propertyMap.keySet()) {
if (!property.isPresent(configuration)) { if (!property.isPresent(configuration)) {
return false; return false;
@ -84,16 +76,16 @@ public final class SettingsMigrationService {
* Check if {@code Email.mailText} is present and move it to the Email.html file if it doesn't exist yet. * Check if {@code Email.mailText} is present and move it to the Email.html file if it doesn't exist yet.
* *
* @param configuration The file configuration to verify * @param configuration The file configuration to verify
* @param dataFolder The plugin data folder * @param pluginFolder The plugin data folder
* @return True if a migration has been completed, false otherwise * @return True if a migration has been completed, false otherwise
*/ */
private static boolean performMailTextToFileMigration(FileConfiguration configuration, File dataFolder) { private static boolean performMailTextToFileMigration(FileConfiguration configuration, File pluginFolder) {
final String oldSettingPath = "Email.mailText"; final String oldSettingPath = "Email.mailText";
if (!configuration.contains(oldSettingPath)) { if (!configuration.contains(oldSettingPath)) {
return false; return false;
} }
final File emailFile = new File(dataFolder, "email.html"); final File emailFile = new File(pluginFolder, "email.html");
final String mailText = configuration.getString(oldSettingPath) final String mailText = configuration.getString(oldSettingPath)
.replace("<playername>", "<playername />") .replace("<playername>", "<playername />")
.replace("<servername>", "<servername />") .replace("<servername>", "<servername />")
@ -131,41 +123,4 @@ public final class SettingsMigrationService {
return false; return false;
} }
// -------
// Utilities
// -------
/**
* Copy a resource file (from the JAR) to the given file if it doesn't exist.
*
* @param destinationFile The file to check and copy to (outside of JAR)
* @param resourcePath Absolute path to the resource file (path to file within JAR)
* @return False if the file does not exist and could not be copied, true otherwise
*/
public static boolean copyFileFromResource(File destinationFile, String resourcePath) {
if (destinationFile.exists()) {
return true;
} else if (!destinationFile.getParentFile().exists() && !destinationFile.getParentFile().mkdirs()) {
ConsoleLogger.showError("Cannot create parent directories for '" + destinationFile + "'");
return false;
}
// ClassLoader#getResourceAsStream does not deal with the '\' path separator: replace to '/'
final String normalizedPath = resourcePath.replace("\\", "/");
try (InputStream is = AuthMe.class.getClassLoader().getResourceAsStream(normalizedPath)) {
if (is == null) {
ConsoleLogger.showError(format("Cannot copy resource '%s' to file '%s': cannot load resource",
resourcePath, destinationFile.getPath()));
} else {
Files.copy(is, destinationFile.toPath());
return true;
}
} catch (IOException e) {
ConsoleLogger.logException(format("Cannot copy resource '%s' to file '%s':",
resourcePath, destinationFile.getPath()), e);
}
return false;
}
} }

View File

@ -1,148 +0,0 @@
package fr.xephi.authme.settings;
import com.onarandombox.MultiverseCore.api.MVWorldManager;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.io.File;
/**
* @author Xephi59
* @version $Revision: 1.0 $
*/
public class Spawn extends CustomConfiguration {
private static Spawn spawn;
private static String[] spawnPriority;
private Spawn() {
super(new File(Settings.PLUGIN_FOLDER, "spawn.yml"));
load();
save();
spawnPriority = Settings.spawnPriority.split(",");
}
public static void reload() {
spawn = new Spawn();
}
/**
* Method getInstance.
*
* @return Spawn
*/
public static Spawn getInstance() {
if (spawn == null) {
spawn = new Spawn();
}
return spawn;
}
public boolean setSpawn(Location location) {
if (location == null || location.getWorld() == null) {
return false;
}
set("spawn.world", location.getWorld().getName());
set("spawn.x", location.getX());
set("spawn.y", location.getY());
set("spawn.z", location.getZ());
set("spawn.yaw", location.getYaw());
set("spawn.pitch", location.getPitch());
save();
return true;
}
public boolean setFirstSpawn(Location location) {
if (location == null || location.getWorld() == null) {
return false;
}
set("firstspawn.world", location.getWorld().getName());
set("firstspawn.x", location.getX());
set("firstspawn.y", location.getY());
set("firstspawn.z", location.getZ());
set("firstspawn.yaw", location.getYaw());
set("firstspawn.pitch", location.getPitch());
save();
return true;
}
public Location getSpawn() {
if (containsAll("spawn.world", "spawn.x", "spawn.y", "spawn.z", "spawn.yaw", "spawn.pitch")) {
String worldName = getString("spawn.world");
World world = Bukkit.getWorld(worldName);
if (!StringUtils.isEmpty(worldName) && world != null) {
return new Location(
world, getDouble("spawn.x"), getDouble("spawn.y"), getDouble("spawn.z"),
Float.parseFloat(getString("spawn.yaw")), Float.parseFloat(getString("spawn.pitch"))
);
}
}
return null;
}
public Location getFirstSpawn() {
if (containsAll("firstspawn.world", "firstspawn.x", "firstspawn.y",
"firstspawn.z", "firstspawn.yaw", "firstspawn.pitch")) {
String worldName = getString("firstspawn.world");
World world = Bukkit.getWorld(worldName);
if (!StringUtils.isEmpty(worldName) && world != null) {
return new Location(
world, getDouble("firstspawn.x"), getDouble("firstspawn.y"), getDouble("firstspawn.z"),
Float.parseFloat(getString("firstspawn.yaw")), Float.parseFloat(getString("firstspawn.pitch"))
);
}
}
return null;
}
// Return the spawn location of a player
public Location getSpawnLocation(Player player) {
AuthMe plugin = AuthMe.getInstance();
if (plugin == null || player == null || player.getWorld() == null) {
return null;
}
World world = player.getWorld();
Location spawnLoc = null;
for (String priority : spawnPriority) {
switch (priority.toLowerCase()) {
case "default":
if (world.getSpawnLocation() != null) {
spawnLoc = world.getSpawnLocation();
}
break;
case "multiverse":
if (Settings.multiverse && plugin.multiverse != null) {
MVWorldManager manager = plugin.multiverse.getMVWorldManager();
if (manager.isMVWorld(world)) {
spawnLoc = manager.getMVWorld(world).getSpawnLocation();
}
}
break;
case "essentials":
spawnLoc = plugin.essentialsSpawn;
break;
case "authme":
String playerNameLower = player.getName().toLowerCase();
if (PlayerCache.getInstance().isAuthenticated(playerNameLower)) {
spawnLoc = getSpawn();
} else if ((getFirstSpawn() != null) && (!player.hasPlayedBefore() ||
(!plugin.getDataSource().isAuthAvailable(playerNameLower)))) {
spawnLoc = getFirstSpawn();
} else {
spawnLoc = getSpawn();
}
break;
}
if (spawnLoc != null) {
return spawnLoc;
}
}
return world.getSpawnLocation(); // return default location
}
}

View File

@ -0,0 +1,260 @@
package fr.xephi.authme.settings;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.hooks.PluginHooks;
import fr.xephi.authme.settings.properties.RestrictionSettings;
import fr.xephi.authme.util.FileUtils;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.File;
import java.io.IOException;
/**
* Manager for spawn points. It loads spawn definitions from AuthMe and third-party plugins
* and is responsible for returning the correct spawn point as per the settings.
* <p>
* The spawn priority setting defines from which sources and in which order the spawn point
* should be taken from. In AuthMe, we can distinguish between the regular spawn and a "first spawn",
* to which players will be teleported who have joined for the first time.
*/
public class SpawnLoader {
private final File authMeConfigurationFile;
private final PluginHooks pluginHooks;
private FileConfiguration authMeConfiguration;
private String[] spawnPriority;
private Location essentialsSpawn;
/**
* Constructor.
*
* @param pluginFolder The AuthMe data folder
* @param settings The setting instance
* @param pluginHooks The plugin hooks instance
*/
public SpawnLoader(File pluginFolder, NewSetting settings, PluginHooks pluginHooks) {
File spawnFile = new File(pluginFolder, "spawn.yml");
// TODO ljacqu 20160312: Check if resource could be copied and handle the case if not
FileUtils.copyFileFromResource(spawnFile, "spawn.yml");
this.authMeConfigurationFile = new File(pluginFolder, "spawn.yml");
this.pluginHooks = pluginHooks;
initialize(settings);
}
/**
* Retrieve the relevant settings and load the AuthMe spawn.yml file.
*
* @param settings The settings instance
*/
public void initialize(NewSetting settings) {
spawnPriority = settings.getProperty(RestrictionSettings.SPAWN_PRIORITY).split(",");
authMeConfiguration = YamlConfiguration.loadConfiguration(authMeConfigurationFile);
loadEssentialsSpawn();
}
/**
* Return the AuthMe spawn location.
*
* @return The location of the regular AuthMe spawn point
*/
public Location getSpawn() {
return getLocationFromConfiguration(authMeConfiguration, "spawn");
}
/**
* Set the AuthMe spawn point.
*
* @param location The location to use
* @return True upon success, false otherwise
*/
public boolean setSpawn(Location location) {
return setLocation("spawn", location);
}
/**
* Return the AuthMe first spawn location.
*
* @return The location of the AuthMe spawn point for first timers
*/
public Location getFirstSpawn() {
return getLocationFromConfiguration(authMeConfiguration, "firstspawn");
}
/**
* Set the AuthMe first spawn location.
*
* @param location The location to use
* @return True upon success, false otherwise
*/
public boolean setFirstSpawn(Location location) {
return setLocation("firstspawn", location);
}
/**
* Load the spawn point defined in EssentialsSpawn.
*/
public void loadEssentialsSpawn() {
// EssentialsSpawn cannot run without Essentials, so it's fine to get the Essentials data folder
File essentialsFolder = pluginHooks.getEssentialsDataFolder();
if (essentialsFolder == null) {
return;
}
File essentialsSpawnFile = new File(essentialsFolder, "spawn.yml");
if (essentialsSpawnFile.exists()) {
essentialsSpawn = getLocationFromConfiguration(
YamlConfiguration.loadConfiguration(essentialsSpawnFile), "spawns.default");
} else {
essentialsSpawn = null;
ConsoleLogger.info("Essentials spawn file not found: '" + essentialsSpawnFile.getAbsolutePath() + "'");
}
}
/**
* Unset the spawn point defined in EssentialsSpawn.
*/
public void unloadEssentialsSpawn() {
essentialsSpawn = null;
}
/**
* Return the spawn location for the given player. The source of the spawn location varies
* depending on the spawn priority setting.
*
* @param player The player to retrieve the spawn point for
* @return The spawn location, or the default spawn location upon failure
* @see RestrictionSettings#SPAWN_PRIORITY
*/
public Location getSpawnLocation(Player player) {
AuthMe plugin = AuthMe.getInstance();
if (plugin == null || player == null || player.getWorld() == null) {
return null;
}
World world = player.getWorld();
Location spawnLoc = null;
for (String priority : spawnPriority) {
switch (priority.toLowerCase().trim()) {
case "default":
if (world.getSpawnLocation() != null) {
spawnLoc = world.getSpawnLocation();
}
break;
case "multiverse":
if (Settings.multiverse) {
spawnLoc = pluginHooks.getMultiverseSpawn(world);
}
break;
case "essentials":
spawnLoc = essentialsSpawn;
break;
case "authme":
String playerNameLower = player.getName().toLowerCase();
if (PlayerCache.getInstance().isAuthenticated(playerNameLower)) {
spawnLoc = getSpawn();
} else if (getFirstSpawn() != null && (!player.hasPlayedBefore() ||
!plugin.getDataSource().isAuthAvailable(playerNameLower))) {
spawnLoc = getFirstSpawn();
} else {
spawnLoc = getSpawn();
}
break;
}
if (spawnLoc != null) {
return spawnLoc;
}
}
return world.getSpawnLocation(); // return default location
}
/**
* Save the location under the given prefix.
*
* @param prefix The prefix to save the spawn under
* @param location The location to persist
* @return True upon success, false otherwise
*/
private boolean setLocation(String prefix, Location location) {
if (location != null && location.getWorld() != null) {
authMeConfiguration.set(prefix + ".world", location.getWorld().getName());
authMeConfiguration.set(prefix + ".x", location.getX());
authMeConfiguration.set(prefix + ".y", location.getY());
authMeConfiguration.set(prefix + ".z", location.getZ());
authMeConfiguration.set(prefix + ".yaw", location.getYaw());
authMeConfiguration.set(prefix + ".pitch", location.getPitch());
return saveAuthMeConfig();
}
return false;
}
private boolean saveAuthMeConfig() {
// TODO ljacqu 20160312: Investigate whether this utility should be put in a Utils class
try {
authMeConfiguration.save(authMeConfigurationFile);
return true;
} catch (IOException e) {
ConsoleLogger.logException("Could not save spawn config (" + authMeConfigurationFile + ")", e);
}
return false;
}
/**
* Build a {@link Location} object from the given path in the file configuration.
*
* @param configuration The file configuration to read from
* @param pathPrefix The path to get the spawn point from
* @return Location corresponding to the values in the path
*/
private static Location getLocationFromConfiguration(FileConfiguration configuration, String pathPrefix) {
if (containsAllSpawnFields(configuration, pathPrefix)) {
String prefix = pathPrefix + ".";
String worldName = configuration.getString(prefix + "world");
World world = Bukkit.getWorld(worldName);
if (!StringUtils.isEmpty(worldName) && world != null) {
return new Location(world, configuration.getDouble(prefix + "x"),
configuration.getDouble(prefix + "y"), configuration.getDouble(prefix + "z"),
getFloat(configuration, prefix + "yaw"), getFloat(configuration, prefix + "pitch"));
}
}
return null;
}
/**
* Return whether the file configuration contains all fields necessary to define a spawn
* under the given path.
*
* @param configuration The file configuration to use
* @param pathPrefix The path to verify
* @return True if all spawn fields are present, false otherwise
*/
private static boolean containsAllSpawnFields(FileConfiguration configuration, String pathPrefix) {
String[] fields = {"world", "x", "y", "z", "yaw", "pitch"};
for (String field : fields) {
if (!configuration.contains(pathPrefix + "." + field)) {
return false;
}
}
return true;
}
/**
* Retrieve a property as a float from the given file configuration.
*
* @param configuration The file configuration to use
* @param path The path of the property to retrieve
* @return The float
*/
private static float getFloat(FileConfiguration configuration, String path) {
Object value = configuration.get(path);
// This behavior is consistent with FileConfiguration#getDouble
return (value instanceof Number) ? ((Number) value).floatValue() : 0;
}
}

View File

@ -12,6 +12,6 @@ import java.lang.annotation.Target;
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
public @interface Comment { public @interface Comment {
String[] value(); String[] value();
} }

View File

@ -0,0 +1,49 @@
package fr.xephi.authme.settings.domain;
import org.bukkit.configuration.file.FileConfiguration;
import org.yaml.snakeyaml.Yaml;
/**
* Enum property.
*
* @param <E> The enum class
*/
class EnumProperty<E extends Enum<E>> extends Property<E> {
private Class<E> clazz;
public EnumProperty(Class<E> clazz, String path, E defaultValue) {
super(path, defaultValue);
this.clazz = clazz;
}
@Override
public E getFromFile(FileConfiguration configuration) {
String textValue = configuration.getString(getPath());
if (textValue == null) {
return getDefaultValue();
}
E mappedValue = mapToEnum(textValue);
return mappedValue != null ? mappedValue : getDefaultValue();
}
@Override
public boolean isPresent(FileConfiguration configuration) {
return super.isPresent(configuration) && mapToEnum(configuration.getString(getPath())) != null;
}
@Override
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
E value = getFromFile(configuration);
return singleQuoteYaml.dump(value.name());
}
private E mapToEnum(String value) {
for (E entry : clazz.getEnumConstants()) {
if (entry.name().equalsIgnoreCase(value)) {
return entry;
}
}
return null;
}
}

View File

@ -1,48 +0,0 @@
package fr.xephi.authme.settings.domain;
import org.bukkit.configuration.file.FileConfiguration;
import org.yaml.snakeyaml.Yaml;
/**
* Enum property type.
*
* @param <E> The enum class
*/
class EnumPropertyType<E extends Enum<E>> extends PropertyType<E> {
private Class<E> clazz;
public EnumPropertyType(Class<E> clazz) {
this.clazz = clazz;
}
@Override
public E getFromFile(Property<E> property, FileConfiguration configuration) {
String textValue = configuration.getString(property.getPath());
if (textValue == null) {
return property.getDefaultValue();
}
E mappedValue = mapToEnum(textValue);
return mappedValue != null ? mappedValue : property.getDefaultValue();
}
@Override
public boolean contains(Property<E> property, FileConfiguration configuration) {
return super.contains(property, configuration)
&& mapToEnum(configuration.getString(property.getPath())) != null;
}
@Override
public String toYaml(E value, Yaml simpleYaml, Yaml singleQuoteYaml) {
return singleQuoteYaml.dump(value.name());
}
private E mapToEnum(String value) {
for (E entry : clazz.getEnumConstants()) {
if (entry.name().equalsIgnoreCase(value)) {
return entry;
}
}
return null;
}
}

View File

@ -10,45 +10,27 @@ import java.util.Objects;
/** /**
* Property class, representing a <i>setting</i> that is read from the config.yml file. * Property class, representing a <i>setting</i> that is read from the config.yml file.
*/ */
public class Property<T> { public abstract class Property<T> {
private final PropertyType<T> type;
private final String path; private final String path;
private final T defaultValue; private final T defaultValue;
private Property(PropertyType<T> type, String path, T defaultValue) { protected Property(String path, T defaultValue) {
Objects.requireNonNull(defaultValue); Objects.requireNonNull(defaultValue);
this.type = type;
this.path = path; this.path = path;
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
} }
/** /**
* Create a new property. See also {@link #newProperty(PropertyType, String, Object[])} for lists and * Create a new string list property.
* {@link #newProperty(Class, String, Enum)}.
* *
* @param type The property type
* @param path The property's path * @param path The property's path
* @param defaultValue The default value * @param defaultValues The items in the default list
* @param <T> The type of the property
* @return The created property
*/
public static <T> Property<T> newProperty(PropertyType<T> type, String path, T defaultValue) {
return new Property<>(type, path, defaultValue);
}
/**
* Create a new list property.
*
* @param type The list type of the property
* @param path The property's path
* @param defaultValues The default value's items
* @param <U> The list type
* @return The created list property * @return The created list property
*/ */
@SafeVarargs public static Property<List<String>> newListProperty(String path, String... defaultValues) {
public static <U> Property<List<U>> newProperty(PropertyType<List<U>> type, String path, U... defaultValues) { // does not have the same name as not to clash with #newProperty(String, String)
return new Property<>(type, path, Arrays.asList(defaultValues)); return new StringListProperty(path, defaultValues);
} }
/** /**
@ -61,36 +43,28 @@ public class Property<T> {
* @return The created enum property * @return The created enum property
*/ */
public static <E extends Enum<E>> Property<E> newProperty(Class<E> clazz, String path, E defaultValue) { public static <E extends Enum<E>> Property<E> newProperty(Class<E> clazz, String path, E defaultValue) {
return new Property<>(new EnumPropertyType<>(clazz), path, defaultValue); return new EnumProperty<>(clazz, path, defaultValue);
} }
// -----
// Overloaded convenience methods for specific types
// -----
public static Property<Boolean> newProperty(String path, boolean defaultValue) { public static Property<Boolean> newProperty(String path, boolean defaultValue) {
return new Property<>(PropertyType.BOOLEAN, path, defaultValue); return new BooleanProperty(path, defaultValue);
} }
public static Property<Integer> newProperty(String path, int defaultValue) { public static Property<Integer> newProperty(String path, int defaultValue) {
return new Property<>(PropertyType.INTEGER, path, defaultValue); return new IntegerProperty(path, defaultValue);
} }
public static Property<String> newProperty(String path, String defaultValue) { public static Property<String> newProperty(String path, String defaultValue) {
return new Property<>(PropertyType.STRING, path, defaultValue); return new StringProperty(path, defaultValue);
} }
// -----
// Hooks to the PropertyType methods
// -----
/** /**
* Get the property value from the given configuration &ndash; guaranteed to never return null. * Get the property value from the given configuration &ndash; guaranteed to never return null.
* *
* @param configuration The configuration to read the value from * @param configuration The configuration to read the value from
* @return The value, or default if not present * @return The value, or default if not present
*/ */
public T getFromFile(FileConfiguration configuration) { public abstract T getFromFile(FileConfiguration configuration);
return type.getFromFile(this, configuration);
}
/** /**
* Return whether or not the given configuration file contains the property. * Return whether or not the given configuration file contains the property.
@ -99,7 +73,7 @@ public class Property<T> {
* @return True if the property is present, false otherwise * @return True if the property is present, false otherwise
*/ */
public boolean isPresent(FileConfiguration configuration) { public boolean isPresent(FileConfiguration configuration) {
return type.contains(this, configuration); return configuration.contains(path);
} }
/** /**
@ -111,12 +85,9 @@ public class Property<T> {
* @return The generated YAML * @return The generated YAML
*/ */
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) { public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
return type.toYaml(getFromFile(configuration), simpleYaml, singleQuoteYaml); return simpleYaml.dump(getFromFile(configuration));
} }
// -----
// Trivial getters
// -----
/** /**
* Return the default value of the property. * Return the default value of the property.
* *
@ -140,4 +111,89 @@ public class Property<T> {
return "Property '" + path + "'"; return "Property '" + path + "'";
} }
/**
* Boolean property.
*/
private static final class BooleanProperty extends Property<Boolean> {
public BooleanProperty(String path, Boolean defaultValue) {
super(path, defaultValue);
}
@Override
public Boolean getFromFile(FileConfiguration configuration) {
return configuration.getBoolean(getPath(), getDefaultValue());
}
}
/**
* Integer property.
*/
private static final class IntegerProperty extends Property<Integer> {
public IntegerProperty(String path, Integer defaultValue) {
super(path, defaultValue);
}
@Override
public Integer getFromFile(FileConfiguration configuration) {
return configuration.getInt(getPath(), getDefaultValue());
}
}
/**
* String property.
*/
private static final class StringProperty extends Property<String> {
public StringProperty(String path, String defaultValue) {
super(path, defaultValue);
}
@Override
public String getFromFile(FileConfiguration configuration) {
return configuration.getString(getPath(), getDefaultValue());
}
@Override
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
return singleQuoteYaml.dump(getFromFile(configuration));
}
}
/**
* String list property.
*/
private static final class StringListProperty extends Property<List<String>> {
public StringListProperty(String path, String[] defaultValues) {
super(path, Arrays.asList(defaultValues));
}
@Override
public List<String> getFromFile(FileConfiguration configuration) {
if (!configuration.isList(getPath())) {
return getDefaultValue();
}
return configuration.getStringList(getPath());
}
@Override
public boolean isPresent(FileConfiguration configuration) {
return configuration.isList(getPath());
}
@Override
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
List<String> value = getFromFile(configuration);
String yaml = singleQuoteYaml.dump(value);
// If the property is a non-empty list we need to append a new line because it will be
// something like the following, which requires a new line:
// - 'item 1'
// - 'second item in list'
return value.isEmpty() ? yaml : "\n" + yaml;
}
}
} }

View File

@ -1,116 +0,0 @@
package fr.xephi.authme.settings.domain;
import org.bukkit.configuration.file.FileConfiguration;
import org.yaml.snakeyaml.Yaml;
import java.util.List;
/**
* Handles a certain property type and provides type-specific functionality.
*
* @param <T> The value of the property
* @see Property
*/
public abstract class PropertyType<T> {
public static final PropertyType<Boolean> BOOLEAN = new BooleanProperty();
public static final PropertyType<Integer> INTEGER = new IntegerProperty();
public static final PropertyType<String> STRING = new StringProperty();
public static final PropertyType<List<String>> STRING_LIST = new StringListProperty();
/**
* Get the property's value from the given YAML configuration.
*
* @param property The property to retrieve
* @param configuration The YAML configuration to read from
* @return The read value, or the default value if absent
*/
public abstract T getFromFile(Property<T> property, FileConfiguration configuration);
/**
* Return whether the property is present in the given configuration.
*
* @param property The property to search for
* @param configuration The configuration to verify
* @return True if the property is present, false otherwise
*/
public boolean contains(Property<T> property, FileConfiguration configuration) {
return configuration.contains(property.getPath());
}
/**
* Format the value as YAML.
*
* @param value The value to export
* @param simpleYaml YAML object (default)
* @param singleQuoteYaml YAML object set to use single quotes
* @return The generated YAML
*/
public String toYaml(T value, Yaml simpleYaml, Yaml singleQuoteYaml) {
return simpleYaml.dump(value);
}
/**
* Boolean property.
*/
private static final class BooleanProperty extends PropertyType<Boolean> {
@Override
public Boolean getFromFile(Property<Boolean> property, FileConfiguration configuration) {
return configuration.getBoolean(property.getPath(), property.getDefaultValue());
}
}
/**
* Integer property.
*/
private static final class IntegerProperty extends PropertyType<Integer> {
@Override
public Integer getFromFile(Property<Integer> property, FileConfiguration configuration) {
return configuration.getInt(property.getPath(), property.getDefaultValue());
}
}
/**
* String property.
*/
private static final class StringProperty extends PropertyType<String> {
@Override
public String getFromFile(Property<String> property, FileConfiguration configuration) {
return configuration.getString(property.getPath(), property.getDefaultValue());
}
@Override
public String toYaml(String value, Yaml simpleYaml, Yaml singleQuoteYaml) {
return singleQuoteYaml.dump(value);
}
}
/**
* String list property.
*/
private static final class StringListProperty extends PropertyType<List<String>> {
@Override
public List<String> getFromFile(Property<List<String>> property, FileConfiguration configuration) {
if (!configuration.isList(property.getPath())) {
return property.getDefaultValue();
}
return configuration.getStringList(property.getPath());
}
@Override
public boolean contains(Property<List<String>> property, FileConfiguration configuration) {
return configuration.contains(property.getPath()) && configuration.isList(property.getPath());
}
@Override
public String toYaml(List<String> value, Yaml simpleYaml, Yaml singleQuoteYaml) {
String yaml = singleQuoteYaml.dump(value);
// If the property is a non-empty list we need to append a new line because it will be
// something like the following, which requires a new line:
// - 'item 1'
// - 'second item in list'
return value.isEmpty() ? yaml : "\n" + yaml;
}
}
}

View File

@ -5,26 +5,24 @@ import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.domain.SettingsClass; import fr.xephi.authme.settings.domain.SettingsClass;
import static fr.xephi.authme.settings.domain.Property.newProperty; import static fr.xephi.authme.settings.domain.Property.newProperty;
import static fr.xephi.authme.settings.domain.PropertyType.BOOLEAN;
import static fr.xephi.authme.settings.domain.PropertyType.STRING;
public class ConverterSettings implements SettingsClass { public class ConverterSettings implements SettingsClass {
@Comment("Rakamak file name") @Comment("Rakamak file name")
public static final Property<String> RAKAMAK_FILE_NAME = public static final Property<String> RAKAMAK_FILE_NAME =
newProperty(STRING, "Converter.Rakamak.fileName", "users.rak"); newProperty("Converter.Rakamak.fileName", "users.rak");
@Comment("Rakamak use IP?") @Comment("Rakamak use IP?")
public static final Property<Boolean> RAKAMAK_USE_IP = public static final Property<Boolean> RAKAMAK_USE_IP =
newProperty(BOOLEAN, "Converter.Rakamak.useIP", false); newProperty("Converter.Rakamak.useIP", false);
@Comment("Rakamak IP file name") @Comment("Rakamak IP file name")
public static final Property<String> RAKAMAK_IP_FILE_NAME = public static final Property<String> RAKAMAK_IP_FILE_NAME =
newProperty(STRING, "Converter.Rakamak.ipFileName", "UsersIp.rak"); newProperty("Converter.Rakamak.ipFileName", "UsersIp.rak");
@Comment("CrazyLogin database file name") @Comment("CrazyLogin database file name")
public static final Property<String> CRAZYLOGIN_FILE_NAME = public static final Property<String> CRAZYLOGIN_FILE_NAME =
newProperty(STRING, "Converter.CrazyLogin.fileName", "accounts.db"); newProperty("Converter.CrazyLogin.fileName", "accounts.db");
private ConverterSettings() { private ConverterSettings() {
} }

View File

@ -6,29 +6,26 @@ import fr.xephi.authme.settings.domain.SettingsClass;
import java.util.List; import java.util.List;
import static fr.xephi.authme.settings.domain.Property.newListProperty;
import static fr.xephi.authme.settings.domain.Property.newProperty; import static fr.xephi.authme.settings.domain.Property.newProperty;
import static fr.xephi.authme.settings.domain.PropertyType.BOOLEAN;
import static fr.xephi.authme.settings.domain.PropertyType.INTEGER;
import static fr.xephi.authme.settings.domain.PropertyType.STRING;
import static fr.xephi.authme.settings.domain.PropertyType.STRING_LIST;
public class EmailSettings implements SettingsClass { public class EmailSettings implements SettingsClass {
@Comment("Email SMTP server host") @Comment("Email SMTP server host")
public static final Property<String> SMTP_HOST = public static final Property<String> SMTP_HOST =
newProperty(STRING, "Email.mailSMTP", "smtp.gmail.com"); newProperty("Email.mailSMTP", "smtp.gmail.com");
@Comment("Email SMTP server port") @Comment("Email SMTP server port")
public static final Property<Integer> SMTP_PORT = public static final Property<Integer> SMTP_PORT =
newProperty(INTEGER, "Email.mailPort", 465); newProperty("Email.mailPort", 465);
@Comment("Email account which sends the mails") @Comment("Email account which sends the mails")
public static final Property<String> MAIL_ACCOUNT = public static final Property<String> MAIL_ACCOUNT =
newProperty(STRING, "Email.mailAccount", ""); newProperty("Email.mailAccount", "");
@Comment("Email account password") @Comment("Email account password")
public static final Property<String> MAIL_PASSWORD = public static final Property<String> MAIL_PASSWORD =
newProperty(STRING, "Email.mailPassword", ""); newProperty("Email.mailPassword", "");
@Comment("Custom sender name, replacing the mailAccount name in the email") @Comment("Custom sender name, replacing the mailAccount name in the email")
public static final Property<String> MAIL_SENDER_NAME = public static final Property<String> MAIL_SENDER_NAME =
@ -36,39 +33,39 @@ public class EmailSettings implements SettingsClass {
@Comment("Recovery password length") @Comment("Recovery password length")
public static final Property<Integer> RECOVERY_PASSWORD_LENGTH = public static final Property<Integer> RECOVERY_PASSWORD_LENGTH =
newProperty(INTEGER, "Email.RecoveryPasswordLength", 8); newProperty("Email.RecoveryPasswordLength", 8);
@Comment("Mail Subject") @Comment("Mail Subject")
public static final Property<String> RECOVERY_MAIL_SUBJECT = public static final Property<String> RECOVERY_MAIL_SUBJECT =
newProperty(STRING, "Email.mailSubject", "Your new AuthMe password"); newProperty("Email.mailSubject", "Your new AuthMe password");
@Comment("Like maxRegPerIP but with email") @Comment("Like maxRegPerIP but with email")
public static final Property<Integer> MAX_REG_PER_EMAIL = public static final Property<Integer> MAX_REG_PER_EMAIL =
newProperty(INTEGER, "Email.maxRegPerEmail", 1); newProperty("Email.maxRegPerEmail", 1);
@Comment("Recall players to add an email?") @Comment("Recall players to add an email?")
public static final Property<Boolean> RECALL_PLAYERS = public static final Property<Boolean> RECALL_PLAYERS =
newProperty(BOOLEAN, "Email.recallPlayers", false); newProperty("Email.recallPlayers", false);
@Comment("Delay in minute for the recall scheduler") @Comment("Delay in minute for the recall scheduler")
public static final Property<Integer> DELAY_RECALL = public static final Property<Integer> DELAY_RECALL =
newProperty(INTEGER, "Email.delayRecall", 5); newProperty("Email.delayRecall", 5);
@Comment("Blacklist these domains for emails") @Comment("Blacklist these domains for emails")
public static final Property<List<String>> DOMAIN_BLACKLIST = public static final Property<List<String>> DOMAIN_BLACKLIST =
newProperty(STRING_LIST, "Email.emailBlacklisted", "10minutemail.com"); newListProperty("Email.emailBlacklisted", "10minutemail.com");
@Comment("Whitelist ONLY these domains for emails") @Comment("Whitelist ONLY these domains for emails")
public static final Property<List<String>> DOMAIN_WHITELIST = public static final Property<List<String>> DOMAIN_WHITELIST =
newProperty(STRING_LIST, "Email.emailWhitelisted"); newListProperty("Email.emailWhitelisted");
@Comment("Send the new password drawn in an image?") @Comment("Send the new password drawn in an image?")
public static final Property<Boolean> PASSWORD_AS_IMAGE = public static final Property<Boolean> PASSWORD_AS_IMAGE =
newProperty(BOOLEAN, "Email.generateImage", false); newProperty("Email.generateImage", false);
@Comment("The OAuth2 token") @Comment("The OAuth2 token")
public static final Property<String> OAUTH2_TOKEN = public static final Property<String> OAUTH2_TOKEN =
newProperty(STRING, "Email.emailOauth2Token", ""); newProperty("Email.emailOauth2Token", "");
private EmailSettings() { private EmailSettings() {
} }

View File

@ -2,11 +2,11 @@ package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment; import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property; import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.domain.PropertyType;
import fr.xephi.authme.settings.domain.SettingsClass; import fr.xephi.authme.settings.domain.SettingsClass;
import java.util.List; import java.util.List;
import static fr.xephi.authme.settings.domain.Property.newListProperty;
import static fr.xephi.authme.settings.domain.Property.newProperty; import static fr.xephi.authme.settings.domain.Property.newProperty;
public class HooksSettings implements SettingsClass { public class HooksSettings implements SettingsClass {
@ -48,7 +48,7 @@ public class HooksSettings implements SettingsClass {
@Comment("Other MySQL columns where we need to put the username (case-sensitive)") @Comment("Other MySQL columns where we need to put the username (case-sensitive)")
public static final Property<List<String>> MYSQL_OTHER_USERNAME_COLS = public static final Property<List<String>> MYSQL_OTHER_USERNAME_COLS =
newProperty(PropertyType.STRING_LIST, "ExternalBoardOptions.mySQLOtherUsernameColumns"); newListProperty("ExternalBoardOptions.mySQLOtherUsernameColumns");
@Comment("How much log2 rounds needed in BCrypt (do not change if you do not know what it does)") @Comment("How much log2 rounds needed in BCrypt (do not change if you do not know what it does)")
public static final Property<Integer> BCRYPT_LOG2_ROUND = public static final Property<Integer> BCRYPT_LOG2_ROUND =

View File

@ -6,39 +6,37 @@ import fr.xephi.authme.settings.domain.SettingsClass;
import java.util.List; import java.util.List;
import static fr.xephi.authme.settings.domain.Property.newListProperty;
import static fr.xephi.authme.settings.domain.Property.newProperty; import static fr.xephi.authme.settings.domain.Property.newProperty;
import static fr.xephi.authme.settings.domain.PropertyType.BOOLEAN;
import static fr.xephi.authme.settings.domain.PropertyType.INTEGER;
import static fr.xephi.authme.settings.domain.PropertyType.STRING_LIST;
public class ProtectionSettings implements SettingsClass { public class ProtectionSettings implements SettingsClass {
@Comment("Enable some servers protection (country based login, antibot)") @Comment("Enable some servers protection (country based login, antibot)")
public static final Property<Boolean> ENABLE_PROTECTION = public static final Property<Boolean> ENABLE_PROTECTION =
newProperty(BOOLEAN, "Protection.enableProtection", false); newProperty("Protection.enableProtection", false);
@Comment({"Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes", @Comment({"Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes",
"PLEASE USE QUOTES!"}) "PLEASE USE QUOTES!"})
public static final Property<List<String>> COUNTRIES_WHITELIST = public static final Property<List<String>> COUNTRIES_WHITELIST =
newProperty(STRING_LIST, "Protection.countries", "US", "GB", "A1"); newListProperty("Protection.countries", "US", "GB", "A1");
@Comment({"Countries not allowed to join the server and register", @Comment({"Countries not allowed to join the server and register",
"PLEASE USE QUOTES!"}) "PLEASE USE QUOTES!"})
public static final Property<List<String>> COUNTRIES_BLACKLIST = public static final Property<List<String>> COUNTRIES_BLACKLIST =
newProperty(STRING_LIST, "Protection.countriesBlacklist"); newListProperty("Protection.countriesBlacklist");
@Comment("Do we need to enable automatic antibot system?") @Comment("Do we need to enable automatic antibot system?")
public static final Property<Boolean> ENABLE_ANTIBOT = public static final Property<Boolean> ENABLE_ANTIBOT =
newProperty(BOOLEAN, "Protection.enableAntiBot", false); newProperty("Protection.enableAntiBot", false);
@Comment("Max number of player allowed to login in 5 secs before enable AntiBot system automatically") @Comment("Max number of players allowed to login in 5 secs before the AntiBot system is enabled automatically")
public static final Property<Integer> ANTIBOT_SENSIBILITY = public static final Property<Integer> ANTIBOT_SENSIBILITY =
newProperty(INTEGER, "Protection.antiBotSensibility", 5); newProperty("Protection.antiBotSensibility", 5);
@Comment("Duration in minutes of the antibot automatic system") @Comment("Duration in minutes of the antibot automatic system")
public static final Property<Integer> ANTIBOT_DURATION = public static final Property<Integer> ANTIBOT_DURATION =
newProperty(INTEGER, "Protection.antiBotDuration", 10); newProperty("Protection.antiBotDuration", 10);
private ProtectionSettings() { private ProtectionSettings() {
} }

View File

@ -5,43 +5,40 @@ import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.domain.SettingsClass; import fr.xephi.authme.settings.domain.SettingsClass;
import static fr.xephi.authme.settings.domain.Property.newProperty; import static fr.xephi.authme.settings.domain.Property.newProperty;
import static fr.xephi.authme.settings.domain.PropertyType.BOOLEAN;
import static fr.xephi.authme.settings.domain.PropertyType.INTEGER;
import static fr.xephi.authme.settings.domain.PropertyType.STRING;
public class PurgeSettings implements SettingsClass { public class PurgeSettings implements SettingsClass {
@Comment("If enabled, AuthMe automatically purges old, unused accounts") @Comment("If enabled, AuthMe automatically purges old, unused accounts")
public static final Property<Boolean> USE_AUTO_PURGE = public static final Property<Boolean> USE_AUTO_PURGE =
newProperty(BOOLEAN, "Purge.useAutoPurge", false); newProperty("Purge.useAutoPurge", false);
@Comment("Number of Days an account become Unused") @Comment("Number of Days an account become Unused")
public static final Property<Integer> DAYS_BEFORE_REMOVE_PLAYER = public static final Property<Integer> DAYS_BEFORE_REMOVE_PLAYER =
newProperty(INTEGER, "Purge.daysBeforeRemovePlayer", 60); newProperty("Purge.daysBeforeRemovePlayer", 60);
@Comment("Do we need to remove the player.dat file during purge process?") @Comment("Do we need to remove the player.dat file during purge process?")
public static final Property<Boolean> REMOVE_PLAYER_DAT = public static final Property<Boolean> REMOVE_PLAYER_DAT =
newProperty(BOOLEAN, "Purge.removePlayerDat", false); newProperty("Purge.removePlayerDat", false);
@Comment("Do we need to remove the Essentials/users/player.yml file during purge process?") @Comment("Do we need to remove the Essentials/users/player.yml file during purge process?")
public static final Property<Boolean> REMOVE_ESSENTIALS_FILES = public static final Property<Boolean> REMOVE_ESSENTIALS_FILES =
newProperty(BOOLEAN, "Purge.removeEssentialsFile", false); newProperty("Purge.removeEssentialsFile", false);
@Comment("World where are players.dat stores") @Comment("World where are players.dat stores")
public static final Property<String> DEFAULT_WORLD = public static final Property<String> DEFAULT_WORLD =
newProperty(STRING, "Purge.defaultWorld", "world"); newProperty("Purge.defaultWorld", "world");
@Comment("Do we need to remove LimitedCreative/inventories/player.yml, player_creative.yml files during purge process ?") @Comment("Do we need to remove LimitedCreative/inventories/player.yml, player_creative.yml files during purge process ?")
public static final Property<Boolean> REMOVE_LIMITED_CREATIVE_INVENTORIES = public static final Property<Boolean> REMOVE_LIMITED_CREATIVE_INVENTORIES =
newProperty(BOOLEAN, "Purge.removeLimitedCreativesInventories", false); newProperty("Purge.removeLimitedCreativesInventories", false);
@Comment("Do we need to remove the AntiXRayData/PlayerData/player file during purge process?") @Comment("Do we need to remove the AntiXRayData/PlayerData/player file during purge process?")
public static final Property<Boolean> REMOVE_ANTI_XRAY_FILE = public static final Property<Boolean> REMOVE_ANTI_XRAY_FILE =
newProperty(BOOLEAN, "Purge.removeAntiXRayFile", false); newProperty("Purge.removeAntiXRayFile", false);
@Comment("Do we need to remove permissions?") @Comment("Do we need to remove permissions?")
public static final Property<Boolean> REMOVE_PERMISSIONS = public static final Property<Boolean> REMOVE_PERMISSIONS =
newProperty(BOOLEAN, "Purge.removePermissions", false); newProperty("Purge.removePermissions", false);
private PurgeSettings() { private PurgeSettings() {
} }

View File

@ -2,11 +2,11 @@ package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment; import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property; import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.domain.PropertyType;
import fr.xephi.authme.settings.domain.SettingsClass; import fr.xephi.authme.settings.domain.SettingsClass;
import java.util.List; import java.util.List;
import static fr.xephi.authme.settings.domain.Property.newListProperty;
import static fr.xephi.authme.settings.domain.Property.newProperty; import static fr.xephi.authme.settings.domain.Property.newProperty;
public class RegistrationSettings implements SettingsClass { public class RegistrationSettings implements SettingsClass {
@ -39,7 +39,7 @@ public class RegistrationSettings implements SettingsClass {
newProperty("settings.registration.doubleEmailCheck", false); newProperty("settings.registration.doubleEmailCheck", false);
@Comment({ @Comment({
"Do we force kicking player after a successful registration?", "Do we force kick a player after a successful registration?",
"Do not use with login feature below"}) "Do not use with login feature below"})
public static final Property<Boolean> FORCE_KICK_AFTER_REGISTER = public static final Property<Boolean> FORCE_KICK_AFTER_REGISTER =
newProperty("settings.registration.forceKickAfterRegister", false); newProperty("settings.registration.forceKickAfterRegister", false);
@ -50,21 +50,21 @@ public class RegistrationSettings implements SettingsClass {
@Comment("Force these commands after /login, without any '/', use %p to replace with player name") @Comment("Force these commands after /login, without any '/', use %p to replace with player name")
public static final Property<List<String>> FORCE_COMMANDS = public static final Property<List<String>> FORCE_COMMANDS =
newProperty(PropertyType.STRING_LIST, "settings.forceCommands"); newListProperty("settings.forceCommands");
@Comment("Force these commands after /login as service console, without any '/'. " @Comment("Force these commands after /login as service console, without any '/'. "
+ "Use %p to replace with player name") + "Use %p to replace with player name")
public static final Property<List<String>> FORCE_COMMANDS_AS_CONSOLE = public static final Property<List<String>> FORCE_COMMANDS_AS_CONSOLE =
newProperty(PropertyType.STRING_LIST, "settings.forceCommandsAsConsole"); newListProperty("settings.forceCommandsAsConsole");
@Comment("Force these commands after /register, without any '/', use %p to replace with player name") @Comment("Force these commands after /register, without any '/', use %p to replace with player name")
public static final Property<List<String>> FORCE_REGISTER_COMMANDS = public static final Property<List<String>> FORCE_REGISTER_COMMANDS =
newProperty(PropertyType.STRING_LIST, "settings.forceRegisterCommands"); newListProperty("settings.forceRegisterCommands");
@Comment("Force these commands after /register as a server console, without any '/'. " @Comment("Force these commands after /register as a server console, without any '/'. "
+ "Use %p to replace with player name") + "Use %p to replace with player name")
public static final Property<List<String>> FORCE_REGISTER_COMMANDS_AS_CONSOLE = public static final Property<List<String>> FORCE_REGISTER_COMMANDS_AS_CONSOLE =
newProperty(PropertyType.STRING_LIST, "settings.forceRegisterCommandsAsConsole"); newListProperty("settings.forceRegisterCommandsAsConsole");
@Comment({ @Comment({
"Enable to display the welcome message (welcome.txt) after a registration or a login", "Enable to display the welcome message (welcome.txt) after a registration or a login",

View File

@ -2,11 +2,11 @@ package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment; import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property; import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.domain.PropertyType;
import fr.xephi.authme.settings.domain.SettingsClass; import fr.xephi.authme.settings.domain.SettingsClass;
import java.util.List; import java.util.List;
import static fr.xephi.authme.settings.domain.Property.newListProperty;
import static fr.xephi.authme.settings.domain.Property.newProperty; import static fr.xephi.authme.settings.domain.Property.newProperty;
public class RestrictionSettings implements SettingsClass { public class RestrictionSettings implements SettingsClass {
@ -26,7 +26,7 @@ public class RestrictionSettings implements SettingsClass {
@Comment("Allowed commands for unauthenticated players") @Comment("Allowed commands for unauthenticated players")
public static final Property<List<String>> ALLOW_COMMANDS = public static final Property<List<String>> ALLOW_COMMANDS =
newProperty(PropertyType.STRING_LIST, "settings.restrictions.allowCommands", newListProperty("settings.restrictions.allowCommands",
"login", "register", "l", "reg", "email", "captcha"); "login", "register", "l", "reg", "email", "captcha");
@Comment("Max number of allowed registrations per IP") @Comment("Max number of allowed registrations per IP")
@ -64,7 +64,7 @@ public class RestrictionSettings implements SettingsClass {
@Comment({ @Comment({
"To activate the restricted user feature you need", "To activate the restricted user feature you need",
"to enable this option and configure the AllowedRestrctedUser field."}) "to enable this option and configure the AllowedRestrictedUser field."})
public static final Property<Boolean> ENABLE_RESTRICTED_USERS = public static final Property<Boolean> ENABLE_RESTRICTED_USERS =
newProperty("settings.restrictions.AllowRestrictedUser", false); newProperty("settings.restrictions.AllowRestrictedUser", false);
@ -75,7 +75,7 @@ public class RestrictionSettings implements SettingsClass {
" AllowedRestrictedUser:", " AllowedRestrictedUser:",
" - playername;127.0.0.1"}) " - playername;127.0.0.1"})
public static final Property<List<String>> ALLOWED_RESTRICTED_USERS = public static final Property<List<String>> ALLOWED_RESTRICTED_USERS =
newProperty(PropertyType.STRING_LIST, "settings.restrictions.AllowedRestrictedUser"); newListProperty("settings.restrictions.AllowedRestrictedUser");
@Comment("Should unregistered players be kicked immediately?") @Comment("Should unregistered players be kicked immediately?")
public static final Property<Boolean> KICK_NON_REGISTERED = public static final Property<Boolean> KICK_NON_REGISTERED =
@ -148,7 +148,7 @@ public class RestrictionSettings implements SettingsClass {
"WorldNames where we need to force the spawn location for ForceSpawnLocOnJoinEnabled", "WorldNames where we need to force the spawn location for ForceSpawnLocOnJoinEnabled",
"Case-sensitive!"}) "Case-sensitive!"})
public static final Property<List<String>> FORCE_SPAWN_ON_WORLDS = public static final Property<List<String>> FORCE_SPAWN_ON_WORLDS =
newProperty(PropertyType.STRING_LIST, "settings.restrictions.ForceSpawnOnTheseWorlds", newListProperty("settings.restrictions.ForceSpawnOnTheseWorlds",
"world", "world_nether", "world_the_end"); "world", "world_nether", "world_the_end");
@Comment("Ban ip when the ip is not the ip registered in database") @Comment("Ban ip when the ip is not the ip registered in database")
@ -189,7 +189,7 @@ public class RestrictionSettings implements SettingsClass {
"It is case-sensitive!" "It is case-sensitive!"
}) })
public static final Property<List<String>> UNRESTRICTED_NAMES = public static final Property<List<String>> UNRESTRICTED_NAMES =
newProperty(PropertyType.STRING_LIST, "settings.unrestrictions.UnrestrictedName"); newListProperty("settings.unrestrictions.UnrestrictedName");
private RestrictionSettings() { private RestrictionSettings() {

View File

@ -7,8 +7,8 @@ import fr.xephi.authme.settings.domain.SettingsClass;
import java.util.List; import java.util.List;
import static fr.xephi.authme.settings.domain.Property.newListProperty;
import static fr.xephi.authme.settings.domain.Property.newProperty; import static fr.xephi.authme.settings.domain.Property.newProperty;
import static fr.xephi.authme.settings.domain.PropertyType.STRING_LIST;
public class SecuritySettings implements SettingsClass { public class SecuritySettings implements SettingsClass {
@ -98,8 +98,7 @@ public class SecuritySettings implements SettingsClass {
"- '123456'", "- '123456'",
"- 'password'"}) "- 'password'"})
public static final Property<List<String>> UNSAFE_PASSWORDS = public static final Property<List<String>> UNSAFE_PASSWORDS =
newProperty(STRING_LIST, "settings.security.unsafePasswords", newListProperty("settings.security.unsafePasswords", "123456", "password", "qwerty", "12345", "54321");
"123456", "password", "qwerty", "12345", "54321");
private SecuritySettings() { private SecuritySettings() {
} }

View File

@ -1,5 +1,7 @@
package fr.xephi.authme.settings.propertymap; package fr.xephi.authme.settings.propertymap;
import fr.xephi.authme.ConsoleLogger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -37,14 +39,13 @@ final class Node {
} }
/** /**
* Add a node to the root, creating any intermediary children that don't exist. * Add a child node, creating any intermediary children that don't exist.
* *
* @param root The root to add the path to
* @param fullPath The entire path of the node to add, separate by periods * @param fullPath The entire path of the node to add, separate by periods
*/ */
public static void addNode(Node root, String fullPath) { public void addNode(String fullPath) {
String[] pathParts = fullPath.split("\\."); String[] pathParts = fullPath.split("\\.");
Node parent = root; Node parent = this;
for (String part : pathParts) { for (String part : pathParts) {
Node child = parent.getChild(part); Node child = parent.getChild(part);
if (child == null) { if (child == null) {
@ -59,17 +60,16 @@ final class Node {
* Compare two nodes by this class' sorting behavior (insertion order). * Compare two nodes by this class' sorting behavior (insertion order).
* Note that this method assumes that both supplied paths exist in the tree. * Note that this method assumes that both supplied paths exist in the tree.
* *
* @param root The root of the tree
* @param fullPath1 The full path to the first node * @param fullPath1 The full path to the first node
* @param fullPath2 The full path to the second node * @param fullPath2 The full path to the second node
* @return The comparison result, in the same format as {@link Comparable#compareTo} * @return The comparison result, in the same format as {@link Comparable#compareTo}
*/ */
public static int compare(Node root, String fullPath1, String fullPath2) { public int compare(String fullPath1, String fullPath2) {
String[] path1 = fullPath1.split("\\."); String[] path1 = fullPath1.split("\\.");
String[] path2 = fullPath2.split("\\."); String[] path2 = fullPath2.split("\\.");
int commonCount = 0; int commonCount = 0;
Node commonNode = root; Node commonNode = this;
while (commonCount < path1.length && commonCount < path2.length while (commonCount < path1.length && commonCount < path2.length
&& path1[commonCount].equals(path2[commonCount]) && commonNode != null) { && path1[commonCount].equals(path2[commonCount]) && commonNode != null) {
commonNode = commonNode.getChild(path1[commonCount]); commonNode = commonNode.getChild(path1[commonCount]);
@ -77,7 +77,7 @@ final class Node {
} }
if (commonNode == null) { if (commonNode == null) {
System.err.println("Could not find common node for '" + fullPath1 + "' at index " + commonCount); ConsoleLogger.showError("Could not find common node for '" + fullPath1 + "' at index " + commonCount);
return fullPath1.compareTo(fullPath2); // fallback return fullPath1.compareTo(fullPath2); // fallback
} else if (commonCount >= path1.length || commonCount >= path2.length) { } else if (commonCount >= path1.length || commonCount >= path2.length) {
return Integer.compare(path1.length, path2.length); return Integer.compare(path1.length, path2.length);

Some files were not shown because too many files have changed in this diff Show More