diff --git a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java index bbbdcf28..ef1e2c7a 100644 --- a/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/HelpCommand.java @@ -36,7 +36,8 @@ public class HelpCommand implements ExecutableCommand { } } - if (arguments.size() == 1) { + int mappedCommandLevel = foundCommandResult.getCommandDescription().getLabelCount(); + if (mappedCommandLevel == 1) { commandService.outputHelp(sender, result, HelpProvider.SHOW_CHILDREN); } else { commandService.outputHelp(sender, result, HelpProvider.ALL_OPTIONS); diff --git a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java index c5bf2ccd..f05d2117 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpProvider.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpProvider.java @@ -110,7 +110,7 @@ public class HelpProvider { private static void printAlternatives(CommandDescription command, List correctLabels, List lines) { // TODO ljacqu 20151219: Need to show alternatives for base labels too? E.g. /r for /register - if (command.getLabels().size() <= 1) { + if (command.getLabels().size() <= 1 || correctLabels.size() <= 1) { return; } diff --git a/src/main/java/fr/xephi/authme/mail/SendMailSSL.java b/src/main/java/fr/xephi/authme/mail/SendMailSSL.java index ab718b61..692497d0 100644 --- a/src/main/java/fr/xephi/authme/mail/SendMailSSL.java +++ b/src/main/java/fr/xephi/authme/mail/SendMailSSL.java @@ -96,6 +96,7 @@ public class SendMailSSL { int port = Settings.getMailPort; HtmlEmail email = new HtmlEmail(); + email.setCharset(org.apache.commons.mail.EmailConstants.UTF_8); email.setSmtpPort(port); email.setHostName(Settings.getmailSMTP); email.addTo(auth.getEmail()); @@ -129,7 +130,8 @@ public class SendMailSSL { return mailText.replace("", auth.getNickname()).replace("", plugin.getServer().getServerName()).replace("", newPass); } - private static void setPropertiesForPort(HtmlEmail email, int port) + @SuppressWarnings("deprecation") + private static void setPropertiesForPort(HtmlEmail email, int port) throws EmailException { switch (port) { case 587: diff --git a/src/main/java/fr/xephi/authme/settings/Settings.java b/src/main/java/fr/xephi/authme/settings/Settings.java index dfebd88f..6094bd7e 100644 --- a/src/main/java/fr/xephi/authme/settings/Settings.java +++ b/src/main/java/fr/xephi/authme/settings/Settings.java @@ -168,6 +168,7 @@ public final class Settings { isForceSingleSessionEnabled = configFile.getBoolean("settings.restrictions.ForceSingleSession", true); isForceSpawnLocOnJoinEnabled = configFile.getBoolean("settings.restrictions.ForceSpawnLocOnJoinEnabled", false); isSaveQuitLocationEnabled = configFile.getBoolean("settings.restrictions.SaveQuitLocation", false); + isForceSurvivalModeEnabled = configFile.getBoolean("settings.GameMode.ForceSurvivalMode", false); getmaxRegPerIp = configFile.getInt("settings.restrictions.maxRegPerIp", 1); getPasswordHash = getPasswordHash(); getUnloggedinGroup = configFile.getString("settings.security.unLoggedinGroup", "unLoggedInGroup"); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 8959f33b..4c3ac885 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -128,7 +128,7 @@ settings: # Enable double check of password when you register # when it's true, registration require that kind of command: # /register - enablePasswordVerifier: true + enablePasswordConfirmation: true # Should we protect the player inventory before logging in? ProtectInventoryBeforeLogIn: true # Should we display all other accounts from a player when he joins? diff --git a/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java b/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java index 8365f01b..ea18df9a 100644 --- a/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java +++ b/src/test/java/fr/xephi/authme/security/crypts/AbstractEncryptionMethodTest.java @@ -1,7 +1,6 @@ package fr.xephi.authme.security.crypts; import fr.xephi.authme.security.PasswordSecurity; -import org.junit.Ignore; import org.junit.Test; import java.security.NoSuchAlgorithmException; @@ -17,13 +16,33 @@ import static org.junit.Assert.assertTrue; // TODO #358: Remove NoSuchAlgorithm try-catch-es when no longer necessary public abstract class AbstractEncryptionMethodTest { + /** The username used to query {@link EncryptionMethod#comparePassword}. */ public static final String USERNAME = "Test_Player00"; + /** + * List of passwords whose hash is provided to the class to test against; this verifies that previously constructed + * hashes remain valid. + */ public static final String[] GIVEN_PASSWORDS = {"password", "PassWord1", "&^%te$t?Pw@_", "âË_3(íù*"}; + /** + * List of passwords that are hashed at runtime and then tested against; this verifies that hashes that are + * generated are valid. + */ private static final String[] INTERNAL_PASSWORDS = {"test1234", "Ab_C73", "(!#&$~`_-Aa0", "Ûïé1&?+A"}; + /** The encryption method to test. */ private EncryptionMethod method; + /** Map with the hashes against which the entries in GIVEN_PASSWORDS are tested. */ private Map hashes; + /** + * Create a new test for the given encryption method. + * + * @param method The encryption method to test + * @param hash0 The pre-generated hash for the first {@link #GIVEN_PASSWORDS} + * @param hash1 The pre-generated hash for the second {@link #GIVEN_PASSWORDS} + * @param hash2 The pre-generated hash for the third {@link #GIVEN_PASSWORDS} + * @param hash3 The pre-generated hash for the fourth {@link #GIVEN_PASSWORDS} + */ public AbstractEncryptionMethodTest(EncryptionMethod method, String hash0, String hash1, String hash2, String hash3) { this.method = method; @@ -36,13 +55,21 @@ public abstract class AbstractEncryptionMethodTest { @Test public void testGivenPasswords() { - for (String password : GIVEN_PASSWORDS) { - try { - assertTrue("Hash for password '" + password + "' should match", - method.comparePassword(hashes.get(password), password, USERNAME)); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException("EncryptionMethod '" + method + "' threw exception", e); - } + // Test all entries in GIVEN_PASSWORDS except the last one + for (int i = 0; i < GIVEN_PASSWORDS.length - 1; ++i) { + String password = GIVEN_PASSWORDS[i]; + assertTrue("Hash for password '" + password + "' should match", + doesGivenHashMatch(password, method)); + } + + // Note #375: Windows console seems to use its own character encoding (Windows-1252?) and it seems impossible to + // force it to use UTF-8, so passwords with non-ASCII characters will fail. Since we do not recommend to use + // such characters in passwords (something outside of our control, e.g. a database system, might also cause + // problems), we will check the last password in GIVEN_PASSWORDS in a non-failing way; if the hash doesn't match + // we'll just issue a message to System.err + String lastPassword = GIVEN_PASSWORDS[GIVEN_PASSWORDS.length - 1]; + if (!doesGivenHashMatch(lastPassword, method)) { + System.err.println("Note: Hash for password '" + lastPassword + "' does not match for method " + method); } } @@ -67,6 +94,14 @@ public abstract class AbstractEncryptionMethodTest { } } + private boolean doesGivenHashMatch(String password, EncryptionMethod method) { + try { + return method.comparePassword(hashes.get(password), password, USERNAME); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("EncryptionMethod '" + method + "' threw exception", e); + } + } + // @org.junit.Test public void a() { AbstractEncryptionMethodTest.generateTest(); } // TODO #364: Remove this method static void generateTest(EncryptionMethod method) { @@ -85,7 +120,7 @@ public abstract class AbstractEncryptionMethodTest { System.out.println("\t\t\"" + method.computeHash(password, getSalt(method), USERNAME) + "\"" + delim + "// " + password); } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("Could not generate hash", e); + throw new IllegalStateException("Could not generate hash", e); } } System.out.println("\t}"); @@ -115,9 +150,9 @@ public abstract class AbstractEncryptionMethodTest { return BCRYPT.gensalt(8); } } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - throw new RuntimeException("Unknown EncryptionMethod for salt generation"); + throw new RuntimeException(e); + } + throw new IllegalStateException("Unknown EncryptionMethod for salt generation"); } }