WIP cleanup (1/?)
This commit is contained in:
parent
06be8ea6f4
commit
8ca3374c16
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
|
||||
<module name="Checker">
|
||||
<property name="charset" value="UTF-8"/>
|
||||
|
|
|
@ -38,7 +38,6 @@ exclude_patterns:
|
|||
- 'src/main/java/fr/xephi/authme/mail/OAuth2SaslClient.java'
|
||||
- 'src/main/java/fr/xephi/authme/mail/OAuth2SaslClientFactory.java'
|
||||
- 'src/main/java/fr/xephi/authme/security/crypts/PhpBB.java'
|
||||
- 'src/main/java/fr/xephi/authme/security/crypts/Whirlpool.java'
|
||||
- 'src/main/java/fr/xephi/authme/security/crypts/Wordpress.java'
|
||||
# Don't check test classes
|
||||
- 'src/test/java/**/*Test.java'
|
||||
|
|
|
@ -24,6 +24,7 @@ hs_err_pid*
|
|||
|
||||
# Include the project's code style settings file
|
||||
!.idea/codeStyleSettings.xml
|
||||
!.idea/misc.xml
|
||||
|
||||
# File-based project format:
|
||||
*.ipr
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<list size="2">
|
||||
<item index="0" class="java.lang.String" itemvalue="javax.inject.Inject" />
|
||||
<item index="1" class="java.lang.String" itemvalue="org.bukkit.event.EventHandler" />
|
||||
</list>
|
||||
<writeAnnotations>
|
||||
<writeAnnotation name="ch.jalu.injector.testing.InjectDelayed" />
|
||||
<writeAnnotation name="fr.xephi.authme.initialization.DataFolder" />
|
||||
<writeAnnotation name="javax.inject.Inject" />
|
||||
</writeAnnotations>
|
||||
</component>
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
39
README.md
39
README.md
|
@ -90,23 +90,28 @@ You can also create your own translation file and, if you want, you can share it
|
|||
- **Dev resources:**
|
||||
- <a href="https://ci.codemc.org/job/AuthMe/job/AuthMeReloaded/javadoc/">JavaDocs</a>
|
||||
- <a href="http://repo.codemc.org/repository/maven-public/">Maven Repository</a>
|
||||
```xml
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.xephi</groupId>
|
||||
<artifactId>authme</artifactId>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
```
|
||||
- Maven dependency usage:
|
||||
```xml
|
||||
<project>
|
||||
...
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
...
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>fr.xephi</groupId>
|
||||
<artifactId>authme</artifactId>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
...
|
||||
</project>
|
||||
```
|
||||
|
||||
- **Statistics:**
|
||||
![Graph](https://bstats.org/signatures/bukkit/AuthMe.svg)
|
||||
|
|
6
pom.xml
6
pom.xml
|
@ -622,6 +622,12 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>17.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Keep in sync with spigot 1.8.8 -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
|
|
|
@ -1,570 +0,0 @@
|
|||
# =======================================================================================================
|
||||
# _____ __ .__ _____ __________ .__ .___ .___
|
||||
# / _ \ __ ___/ |_| |__ / \ ____\______ \ ____ | | _________ __| _/____ __| _/
|
||||
# / /_\ \| | \ __| | \ / \ / \_/ __ \| __/ __ \| | / _ \__ \ / __ _/ __ \ / __ |
|
||||
# / | | | /| | | Y / Y \ ___/| | \ ___/| |_( <_> / __ \/ /_/ \ ___// /_/ |
|
||||
# \____|__ |____/ |__| |___| \____|__ /\___ |____|_ /\___ |____/\____(____ \____ |\___ \____ |
|
||||
# \/ \/ \/ \/ \/ \/ \/ \/ \/ \/
|
||||
#
|
||||
# =======================================================================================================
|
||||
#
|
||||
# Authme Main Configuration File.
|
||||
#
|
||||
# =======================================================================================================
|
||||
|
||||
# Plugin infos (overwritten on start, just a simple way to find out your plugin version).
|
||||
authors: ${pluginAuthors}
|
||||
version: ${project.version}
|
||||
buildNumber: ${buildNumber}
|
||||
|
||||
# Set this setting to true when you have configured the plugin,
|
||||
# when false the server will be stopped with a warning message.
|
||||
enabled: false
|
||||
|
||||
# Database settings.
|
||||
data_source:
|
||||
# ===========================
|
||||
# Database general settings.
|
||||
# ===========================
|
||||
|
||||
# Database backend (sqlite, mysql).
|
||||
backend: sqlite
|
||||
# Enable database queries caching, should improve performance.
|
||||
caching: true
|
||||
|
||||
# ===========================
|
||||
# SqLite db parameters.
|
||||
# ===========================
|
||||
|
||||
sqlite:
|
||||
# The name of the database storage file.
|
||||
filename: 'authme.db'
|
||||
|
||||
# ===========================
|
||||
# MySql db parameters.
|
||||
# ===========================
|
||||
|
||||
mysql:
|
||||
# Connection parameters.
|
||||
host: '127.0.0.1'
|
||||
port: 3306
|
||||
username: 'change_me'
|
||||
password: 'change_me'
|
||||
database: 'my_minecraft_server'
|
||||
tablename: 'authme'
|
||||
|
||||
# Column names.
|
||||
column_names:
|
||||
id: id
|
||||
# Column for storing nicknames (ignore case nickname).
|
||||
name: username
|
||||
# Column for storing the realname (case sensitive nickname).
|
||||
real_name: realname
|
||||
# Column for storing passwords.
|
||||
password: password
|
||||
# Column for storing email addresses.
|
||||
email: email
|
||||
# Column for storing the authentication status (logged or not).
|
||||
login_status: isLogged
|
||||
# Column for storing player IPs.
|
||||
ip: ip
|
||||
# Column for storing lastlogins date and time.
|
||||
last_login_timestamp: lastlogin
|
||||
# Latest logout location of the players.
|
||||
last_location:
|
||||
world: world
|
||||
x: x
|
||||
y: y
|
||||
z: z
|
||||
# Enabled only if the bungeecord integration is activated.
|
||||
server: world
|
||||
|
||||
# Support for registrations via WebInterfaces/CSM.
|
||||
# Disable some backend caching parameters.
|
||||
disableAggressiveCaching: false
|
||||
|
||||
# Main settings
|
||||
settings:
|
||||
|
||||
# ===========================
|
||||
# Bungeecord integration
|
||||
# ===========================
|
||||
|
||||
bungeecord:
|
||||
# Enable bungeecord integration features
|
||||
enabled: true
|
||||
|
||||
# Server name (must be unique, please use the name in the bungeecord configuration).
|
||||
# Use 'auto' for auto configuration (requires the bungeecord module).
|
||||
serverName: LoginLobby1
|
||||
# Keep the auth status when the player moves between servers.
|
||||
# Required if you're using the bungeecord module.
|
||||
keepAuthBetweenServers: true
|
||||
|
||||
# Target server after login
|
||||
send_after_login:
|
||||
enabled: false
|
||||
message: ''
|
||||
delay: 5
|
||||
# Server name ("ServerName") or group ("G:GroupName")
|
||||
# Groups are avariable only when the bungeecord module is avariable.
|
||||
# If the server change fails the player will be kicked.
|
||||
target: Lobby1
|
||||
failKickMessage: 'Failed to connect to the lobby! Please try to join the server again!'
|
||||
# Target server after logout
|
||||
send_after_logout:
|
||||
enabled: false
|
||||
message: ''
|
||||
delay: 5
|
||||
# Server name ("ServerName") or group ("G:GroupName")
|
||||
# Groups are avariable only when the bungeecord module is avariable.
|
||||
# If the server change fails the player will be kicked.
|
||||
target: LoginLobby1
|
||||
failKickMessage: 'Failed to connect to the lobby! Please try to join the server again!'
|
||||
|
||||
# Variables:
|
||||
# %p playername
|
||||
bungee_commands:
|
||||
player_command_after_register:
|
||||
enabled: false
|
||||
cmd: ''
|
||||
console_command_after_register:
|
||||
enabled: false
|
||||
cmd: 'alert %p joined for the first time the network!'
|
||||
player_command_after_login:
|
||||
enabled: false
|
||||
cmd: 'glist'
|
||||
console_command_after_login:
|
||||
enabled: false
|
||||
cmd: 'alert %p logged in correctly!'
|
||||
player_command_after_join:
|
||||
enabled: false
|
||||
cmd: ''
|
||||
console_command_after_join:
|
||||
enabled: false
|
||||
cmd: 'alert %p joined the network!'
|
||||
player_command_first_join:
|
||||
enabled: false
|
||||
cmd: ''
|
||||
console_command_first_join:
|
||||
enabled: false
|
||||
cmd: 'alert %p joined for the first time the network!'
|
||||
|
||||
# ===========================
|
||||
# Sessions configuration.
|
||||
# ===========================
|
||||
|
||||
sessions:
|
||||
# Enable sessions.
|
||||
# When a player is authenticated, his IP and his nickname is saved.
|
||||
# The next time the player will join the server, if his IP is the same
|
||||
# of the last time, and the timeout time hasn't expired, he will be
|
||||
# automatically authenticated.
|
||||
enabled: false
|
||||
# Session timeout.
|
||||
# 0 for unlimited time (Very dangerous, use it at your own risk!)
|
||||
# Consider that if player's ip has changed but the timeout hasn't
|
||||
# expired, player will be kicked out of the sever!
|
||||
timeout: 10
|
||||
# When enabled a player's session will expire if someone tries to
|
||||
# login with a different IP Address.
|
||||
expire_on_ip_change: true
|
||||
|
||||
# ===========================
|
||||
# Registration settings.
|
||||
# ===========================
|
||||
|
||||
registration:
|
||||
# After how many time unregistered players should be kicked?
|
||||
# Set to 0 to disable. (default: 30)
|
||||
timeout: 30
|
||||
|
||||
nickname:
|
||||
min_length: 4
|
||||
max_lenght: 16
|
||||
# Regex syntax.
|
||||
allowed_characters: '[a-zA-Z0-9_]*'
|
||||
|
||||
password:
|
||||
# Enable double check of password on registration:
|
||||
# /register <password> <confirmPassword>
|
||||
double_check: true
|
||||
# Minimum password lenght.
|
||||
min_length: 5
|
||||
# Regex syntax.
|
||||
allowed_characters: '[\x21-\x7E]*'
|
||||
# Denied unsafe passwords.
|
||||
unsafePasswords:
|
||||
- '123456'
|
||||
- 'password'
|
||||
- 'qwerty'
|
||||
- '12345'
|
||||
- '54321'
|
||||
|
||||
# ===========================
|
||||
# Login settings.
|
||||
# ===========================
|
||||
|
||||
login:
|
||||
# After how many time unlogged players should be kicked?
|
||||
# Set to 0 to disable. (default: 30)
|
||||
timeout: 30
|
||||
|
||||
|
||||
|
||||
# ===========================
|
||||
# Encryption parameters.
|
||||
# ===========================
|
||||
|
||||
password_encryption:
|
||||
# The hashing algorithm.
|
||||
# Possible values: MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB, MYBB, IPB3,
|
||||
# PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5,
|
||||
# PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (developpers only).
|
||||
encryption_algorithm: SHA256
|
||||
# The salt length for the SALTED2MD5 and MD5(MD5(password)+salt) algorithms.
|
||||
md5_salt_length: 8
|
||||
# If password check fails try all the other hash algorithm.
|
||||
# AuthMe will update the password to the new passwordHash.
|
||||
enable_convertion: false
|
||||
|
||||
# ===========================
|
||||
# Unlogged user restrictions.
|
||||
# ===========================
|
||||
|
||||
unlogged_restrictions:
|
||||
# Deny chat messages send for unlogged users.
|
||||
deny_chat: true
|
||||
# Hide chat to unlogged users.
|
||||
# Only player messages, plugins will be able to send messages to the player anyway.
|
||||
hide_chat: false
|
||||
|
||||
# Deny any command message not in the whitelist below.
|
||||
deny_commands: true
|
||||
command_whitelist:
|
||||
- /login
|
||||
- /register
|
||||
- /l
|
||||
- /reg
|
||||
- /email
|
||||
- /captcha
|
||||
|
||||
movements:
|
||||
# Restrict player movements.
|
||||
restrict: true
|
||||
# Allowed radius.
|
||||
allowed_radius: 0
|
||||
# Should unlogged players have speed = 0?
|
||||
# After the login the walking/flying speeed will be reset to the default value.
|
||||
removeSpeed: true
|
||||
|
||||
# End is there atm xD
|
||||
|
||||
# This option will save the quit location of the players.
|
||||
SaveQuitLocation: false
|
||||
# Should not logged in players be teleported to the spawn?
|
||||
# After the authentication, if SaveQuitLocation is enabled,
|
||||
# they will be teleported back to their normal position.
|
||||
teleportUnAuthedToSpawn: false
|
||||
|
||||
# If enabled, after the login, if the ForceSpawnOnTheseWorlds setting contains
|
||||
# the player's world, he will be teleported to the world spawnpoint.
|
||||
# The quit location of the player will be overwritten.
|
||||
# This is different from "teleportUnAuthedToSpawn" that teleports player
|
||||
# back to his quit location after the authentication.
|
||||
ForceSpawnLocOnJoinEnabled: false
|
||||
# WorldNames where we need to force the spawn location
|
||||
# Warning: This setting is Case Sensitive!
|
||||
ForceSpawnOnTheseWorlds:
|
||||
- world
|
||||
- world_nether
|
||||
- world_the_end
|
||||
|
||||
# this is very important options,
|
||||
# every time player join the server,
|
||||
# if they are registered, AuthMe will switch him
|
||||
# to unLoggedInGroup, this
|
||||
# should prevent all major exploit.
|
||||
# So you can set up on your Permission Plugin
|
||||
# this special group with 0 permissions, or permissions to chat,
|
||||
# or permission to
|
||||
# send private message or all other perms that you want,
|
||||
# the better way is to set up
|
||||
# this group with few permissions,
|
||||
# so if player try to exploit some account,
|
||||
# they can
|
||||
# do anything except what you set in perm Group.
|
||||
# After a correct logged-in player will be
|
||||
# moved to his correct permissions group!
|
||||
# Pay attention group name is case sensitive,
|
||||
# so Admin is different from admin,
|
||||
# otherwise your group will be wiped,
|
||||
# and player join in default group []!
|
||||
# Example unLoggedinGroup: NotLogged
|
||||
unLoggedinGroup: unLoggedinGroup
|
||||
|
||||
# ===========================
|
||||
# Address restrictions
|
||||
# ===========================
|
||||
|
||||
# Max number of registrations per IP (default: 1)
|
||||
maxRegPerIp: 1
|
||||
# Maximum allowed number of Logins per IP, 0 to disable (default: 0)
|
||||
maxLoginPerIp: 0
|
||||
# Maximum allowed number of Joins per IP, 0 to disable (default: 0)
|
||||
maxJoinPerIp: 0
|
||||
|
||||
# When this setting is enabled, online players can't be kicked out
|
||||
# due to "Logged in from another Location"
|
||||
# This setting will prevent potential security exploits.
|
||||
ForceSingleSession: true
|
||||
|
||||
# To activate the restricted user feature you need
|
||||
# to enable this option and configure the
|
||||
# AllowedRestrictedUser field.
|
||||
AllowRestrictedUser: false
|
||||
# The restricted user feature will kick players listed below
|
||||
# if they dont match of the defined ip address.
|
||||
# Example:
|
||||
# AllowedRestrictedUser:
|
||||
# - playername;127.0.0.1
|
||||
AllowedRestrictedUser:
|
||||
- playername;127.0.0.
|
||||
# Ban ip when the ip is not the ip registered in database
|
||||
banUnsafedIP: false
|
||||
|
||||
|
||||
|
||||
# ===============================
|
||||
# Other restrictions
|
||||
# ===============================
|
||||
|
||||
# Should we protect the player inventory before logging in?
|
||||
# Warning: Requires the latest version of ProtocolLib!
|
||||
ProtectInventoryBeforeLogIn: true
|
||||
|
||||
# Should unregistered players be kicked immediately?
|
||||
kickNonRegistered: false
|
||||
# Should players be kicked on wrong password?
|
||||
kickOnWrongPassword: false
|
||||
|
||||
# Should we display all other accounts of a player when he joins?
|
||||
# Required permission: authme.admin.accounts
|
||||
displayOtherAccounts: true
|
||||
|
||||
# ===============================
|
||||
# Restrictions compatibility
|
||||
# ===============================
|
||||
|
||||
# Spawn Priority. Avariable values : authme, essentials, multiverse, default
|
||||
spawnPriority: authme,essentials,multiverse,default
|
||||
# AuthMe will NEVER teleport players!
|
||||
noTeleport: false
|
||||
|
||||
GameMode:
|
||||
# Do you want to set player's gamemode to survival when he joins?
|
||||
# This enables also the settings below.
|
||||
ForceSurvivalMode: false
|
||||
# Do you want to reset player's inventory if player joins with creative mode?
|
||||
ResetInventoryIfCreative: false
|
||||
# Do you want to force the survival mode ONLY after the /login process?
|
||||
ForceOnlyAfterLogin: false
|
||||
|
||||
# sgdc3: Ok, our configuration is shit.... xD Today I will stop there
|
||||
|
||||
|
||||
registration:
|
||||
# enable registration on the server?
|
||||
enabled: true
|
||||
# Send every X seconds a message to a player to
|
||||
# remind him that he has to login/register
|
||||
messageInterval: 5
|
||||
# Only registered and logged in players can play.
|
||||
# See restrictions for exceptions
|
||||
force: true
|
||||
# Does we replace password registration by an Email registration method ?
|
||||
enableEmailRegistrationSystem: false
|
||||
# Enable double check of email when you register
|
||||
# when it's true, registration require that kind of command:
|
||||
# /register <email> <confirmEmail>
|
||||
doubleEmailCheck: false
|
||||
# Do we force kicking player after a successful registration ?
|
||||
# Do not use with login feature below
|
||||
forceKickAfterRegister: false
|
||||
# Does AuthMe need to enforce a /login after a successful registration ?
|
||||
forceLoginAfterRegister: false
|
||||
unrestrictions:
|
||||
# below you can list all your account name, that
|
||||
# AuthMe will ignore for registration or login, configure it
|
||||
# at your own risk!! Remember that if you are going to add
|
||||
# nickname with [], you have to delimit name with ' '.
|
||||
# this option add compatibility with BuildCraft and some
|
||||
# other mods.
|
||||
# It is CaseSensitive!
|
||||
UnrestrictedName: []
|
||||
# Message language, available : en, de, br, cz, pl, fr, ru, hu, sk, es, zhtw, fi, zhcn, lt, it, ko, pt
|
||||
messagesLanguage: en
|
||||
# Force these commands after /login, without any '/', use %p for replace with player name
|
||||
forceCommands: []
|
||||
# Force these commands after /login as a server console, without any '/', use %p for replace with player name
|
||||
forceCommandsAsConsole: []
|
||||
# Force these commands after /register, without any '/', use %p for replace with player name
|
||||
forceRegisterCommands: []
|
||||
# Force these commands after /register as a server console, without any '/', use %p for replace with player name
|
||||
forceRegisterCommandsAsConsole: []
|
||||
# Do we need to display the welcome message (welcome.txt) after a register or a login?
|
||||
# You can use colors in this welcome.txt + some replaced strings :
|
||||
# {PLAYER} : player name, {ONLINE} : display number of online players, {MAXPLAYERS} : display server slots,
|
||||
# {IP} : player ip, {LOGINS} : number of players logged, {WORLD} : player current world, {SERVER} : server name
|
||||
# {VERSION} : get current bukkit version, {COUNTRY} : player country
|
||||
useWelcomeMessage: true
|
||||
# Do we need to broadcast the welcome message to all server or only to the player? set true for server or false for player
|
||||
broadcastWelcomeMessage: false
|
||||
# Do we need to delay the join/leave message to be displayed only when the player is authenticated ?
|
||||
delayJoinMessage: false
|
||||
removeJoinMessage: false
|
||||
removeLeaveMessage: false
|
||||
# Do we need to add potion effect Blinding before login/register ?
|
||||
applyBlindEffect: false
|
||||
ExternalBoardOptions:
|
||||
# MySQL column for the salt , needed for some forum/cms support
|
||||
mySQLColumnSalt: ''
|
||||
# MySQL column for the group, needed for some forum/cms support
|
||||
mySQLColumnGroup: ''
|
||||
# -1 mean disabled. If u want that only
|
||||
# activated player can login in your server
|
||||
# u can put in this options the group number
|
||||
# of unactivated user, needed for some forum/cms support
|
||||
nonActivedUserGroup: -1
|
||||
# Other MySQL columns where we need to put the Username (case sensitive)
|
||||
mySQLOtherUsernameColumns: []
|
||||
# How much Log to Round needed in BCrypt(do not change it if you do not know what's your doing)
|
||||
bCryptLog2Round: 10
|
||||
# phpBB prefix defined during phpbb installation process
|
||||
phpbbTablePrefix: 'phpbb_'
|
||||
# phpBB activated group id , 2 is default registered group defined by phpbb
|
||||
phpbbActivatedGroupId: 2
|
||||
# WordPress prefix defined during WordPress installation process
|
||||
wordpressTablePrefix: 'wp_'
|
||||
permission:
|
||||
# Take care with this options, if you dont want
|
||||
# to use Vault and Group Switching of
|
||||
# AuthMe for unloggedIn players put true
|
||||
# below, default is false.
|
||||
EnablePermissionCheck: false
|
||||
BackupSystem:
|
||||
# Enable or Disable Automatic Backup
|
||||
ActivateBackup: false
|
||||
# set Backup at every start of Server
|
||||
OnServerStart: false
|
||||
# set Backup at every stop of Server
|
||||
OnServerStop: true
|
||||
# Windows only mysql installation Path
|
||||
MysqlWindowsPath: 'C:\\Program Files\\MySQL\\MySQL Server 5.1\\'
|
||||
Security:
|
||||
SQLProblem:
|
||||
# Stop the server if we can't contact the sql database
|
||||
# Take care with this, if you set that to false,
|
||||
# AuthMe automatically disable and the server is not protected!
|
||||
stopServer: true
|
||||
ReloadCommand:
|
||||
# /reload support
|
||||
useReloadCommandSupport: true
|
||||
console:
|
||||
# Remove spam console
|
||||
noConsoleSpam: false
|
||||
captcha:
|
||||
# Player need to put a captcha when he fails too lot the password
|
||||
useCaptcha: false
|
||||
# Max allowed tries before request a captcha
|
||||
maxLoginTry: 5
|
||||
# Captcha length
|
||||
captchaLength: 5
|
||||
Converter:
|
||||
Rakamak:
|
||||
# Rakamak file name
|
||||
fileName: users.rak
|
||||
# Rakamak use ip ?
|
||||
useIP: false
|
||||
# IP file name for rakamak
|
||||
ipFileName: UsersIp.rak
|
||||
CrazyLogin:
|
||||
# CrazyLogin database file
|
||||
fileName: accounts.db
|
||||
Email:
|
||||
# Email SMTP server host
|
||||
mailSMTP: smtp.gmail.com
|
||||
# Email SMTP server port
|
||||
mailPort: 465
|
||||
# Email account that send the mail
|
||||
mailAccount: ''
|
||||
# Email account password
|
||||
mailPassword: ''
|
||||
# Custom SenderName, that replace the mailAccount name in the email
|
||||
mailSenderName: ''
|
||||
# Random password length
|
||||
RecoveryPasswordLength: 8
|
||||
# Email subject of password get
|
||||
mailSubject: 'Your new AuthMe Password'
|
||||
# Email text here
|
||||
mailText: 'Dear <playername>, <br /><br /> This is your new AuthMe password for the server <br /><br /> <servername> : <br /><br /> <generatedpass><br /><br />Do not forget to change password after login! <br /> /changepassword <generatedpass> newPassword'
|
||||
# Like maxRegPerIp but with email
|
||||
maxRegPerEmail: 1
|
||||
# Recall players to add an email ?
|
||||
recallPlayers: false
|
||||
# Delay in minute for the recall scheduler
|
||||
delayRecall: 5
|
||||
# Blacklist these domains for emails
|
||||
emailBlacklisted:
|
||||
- 10minutemail.com
|
||||
# WhiteList only these domains for emails
|
||||
emailWhitelisted: []
|
||||
# Do we need to send new password draw in an image ?
|
||||
generateImage: false
|
||||
Hooks:
|
||||
# Do we need to hook with multiverse for spawn checking?
|
||||
multiverse: true
|
||||
# Do we need to hook with BungeeCord for get the real Player ip ?
|
||||
bungeecord: false
|
||||
# Do we need to disable Essentials SocialSpy on join ?
|
||||
disableSocialSpy: true
|
||||
# Do we need to force /motd Essentials command on join ?
|
||||
useEssentialsMotd: false
|
||||
# Do we need to cache custom Attributes ?
|
||||
customAttributes: false
|
||||
Purge:
|
||||
# On Enable , does AuthMe need to purge automatically old accounts unused ?
|
||||
useAutoPurge: false
|
||||
# Number of Days an account become Unused
|
||||
daysBeforeRemovePlayer: 60
|
||||
# Do we need to remove the player.dat file during purge process ?
|
||||
removePlayerDat: false
|
||||
# Do we need to remove the Essentials/users/player.yml file during purge process ?
|
||||
removeEssentialsFile: false
|
||||
# World where are players.dat stores
|
||||
defaultWorld: 'world'
|
||||
# Do we need to remove LimitedCreative/inventories/player.yml , player_creative.yml files during purge process ?
|
||||
removeLimitedCreativesInventories: false
|
||||
# Do we need to remove the AntiXRayData/PlayerData/player file during purge process ?
|
||||
removeAntiXRayFile: false
|
||||
# Do we need to remove permissions ?
|
||||
removePermissions: false
|
||||
Protection:
|
||||
# Enable some servers protection ( country based login, antibot )
|
||||
enableProtection: false
|
||||
# Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes
|
||||
countries:
|
||||
- US
|
||||
- GB
|
||||
# Countries blacklisted automatically ( without any needed to enable protection )
|
||||
countriesBlacklist:
|
||||
- A1
|
||||
# Do we need to enable automatic antibot system?
|
||||
enableAntiBot: false
|
||||
# Max number of player allowed to login in 5 secs before enable AntiBot system automatically
|
||||
antiBotSensibility: 5
|
||||
# Duration in minutes of the antibot automatic system
|
||||
antiBotDuration: 10
|
||||
VeryGames:
|
||||
# These features are only available on VeryGames Server Provider
|
||||
enableIpCheck: false
|
|
@ -1,199 +0,0 @@
|
|||
name: ${pluginName}
|
||||
authors: [${pluginAuthors}]
|
||||
website: ${project.url}
|
||||
description: ${project.description}
|
||||
main: ${mainClass}
|
||||
version: ${project.version}-b${buildNumber}
|
||||
softdepend:
|
||||
- Vault
|
||||
- PermissionsBukkit
|
||||
- PermissionsEX
|
||||
- EssentialsGroupManager
|
||||
- Multiverse-Core
|
||||
- Essentials
|
||||
- EssentialsSpawn
|
||||
- ProtocolLib
|
||||
commands:
|
||||
authme:
|
||||
description: AuthMe admin commands
|
||||
usage: '/authme reload|register playername password|changepassword playername password|unregister playername|version|converter datatype'
|
||||
permission: authme.admin
|
||||
register:
|
||||
description: Register an account
|
||||
usage: /register password confirmpassword
|
||||
aliases: [reg]
|
||||
permission: authme.player.register
|
||||
login:
|
||||
description: Login into a account
|
||||
usage: /login password
|
||||
aliases: [l,log]
|
||||
permission: authme.player.login
|
||||
changepassword:
|
||||
description: Change password of a account
|
||||
usage: /changepassword oldPassword newPassword
|
||||
permission: authme.player.changepassword
|
||||
logout:
|
||||
description: Logout from the server
|
||||
usage: /logout
|
||||
permission: authme.player.logout
|
||||
unregister:
|
||||
description: unregister your account
|
||||
usage: /unregister password
|
||||
permission: authme.player.unregister
|
||||
email:
|
||||
description: Add Email or recover password
|
||||
usage: '/email add your@email.com your@email.com|change oldEmail newEmail|recovery your@email.com'
|
||||
permission: authme.player.email
|
||||
captcha:
|
||||
description: Captcha command
|
||||
usage: /captcha theCaptcha
|
||||
permission: authme.player.captcha
|
||||
permissions:
|
||||
authme.canbeforced:
|
||||
description: Allow the user to be forced-logged via API
|
||||
default: true
|
||||
authme.player:
|
||||
description: Gives access to all authme player commands
|
||||
default: true
|
||||
children:
|
||||
authme.player.login: true
|
||||
authme.player.logout: true
|
||||
authme.player.register: true
|
||||
authme.player.unregister: true
|
||||
authme.player.changepassword: true
|
||||
authme.player.captcha: true
|
||||
authme.player.email: true
|
||||
authme.player.register:
|
||||
description: Register your account
|
||||
default: false
|
||||
authme.player.unregister:
|
||||
description: Unregister your account
|
||||
default: false
|
||||
authme.player.login:
|
||||
description: Login into your account
|
||||
default: false
|
||||
authme.player.logout:
|
||||
description: Logout from your account
|
||||
default: false
|
||||
authme.player.changepassword:
|
||||
description: Change password of your account
|
||||
default: false
|
||||
authme.player.email:
|
||||
description: Gives access to player's email commands
|
||||
default: false
|
||||
children:
|
||||
authme.player.email.add: true
|
||||
authme.player.email.change: true
|
||||
authme.player.email.recover: true
|
||||
authme.player.email.add:
|
||||
description: Add an email to your account
|
||||
default: false
|
||||
authme.player.email.change:
|
||||
description: Change email of your account
|
||||
default: false
|
||||
authme.player.email.recover:
|
||||
description: Recover your account
|
||||
default: false
|
||||
authme.player.captcha:
|
||||
description: Captcha command
|
||||
default: false
|
||||
authme.admin:
|
||||
description: Gives access to all authme admin commands
|
||||
default: op
|
||||
children:
|
||||
authme.admin.forcelogin: true
|
||||
authme.admin.forcelogout: true
|
||||
authme.admin.register: true
|
||||
authme.admin.unregister: true
|
||||
authme.admin.changemail: true
|
||||
authme.admin.changepassword: true
|
||||
authme.admin.lastlogin: true
|
||||
authme.admin.accounts: true
|
||||
authme.admin.getemail: true
|
||||
authme.admin.getip: true
|
||||
authme.admin.setspawn: true
|
||||
authme.admin.spawn: true
|
||||
authme.admin.setfirstspawn: true
|
||||
authme.admin.firstspawn: true
|
||||
authme.admin.purge: true
|
||||
authme.admin.purgebannedplayers: true
|
||||
authme.admin.purgelastpos: true
|
||||
authme.admin.converter: true
|
||||
authme.admin.reload: true
|
||||
authme.admin.switchantibot: true
|
||||
authme.admin.seeotheraccounts: true
|
||||
authme.admin.register:
|
||||
description: Register an account
|
||||
default: false
|
||||
authme.admin.unregister:
|
||||
description: Unregister an account
|
||||
default: false
|
||||
authme.admin.forcelogin:
|
||||
description: Force login for that player
|
||||
default: false
|
||||
authme.admin.forcelogout:
|
||||
description: Force logout for that player
|
||||
default: false
|
||||
authme.admin.changepassword:
|
||||
description: Change the password of an account
|
||||
default: false
|
||||
authme.admin.getemail:
|
||||
description: Get last email about a player
|
||||
default: false
|
||||
authme.admin.changeemail:
|
||||
description: Change a player email
|
||||
default: false
|
||||
authme.admin.accounts:
|
||||
description: Display Players Accounts
|
||||
default: false
|
||||
authme.admin.seeotheraccounts:
|
||||
description: Display other accounts about a player when he logs in
|
||||
default: false
|
||||
authme.admin.lastlogin:
|
||||
description: Get last login date about a player
|
||||
default: false
|
||||
authme.admin.getip:
|
||||
description: Get IP from a player (fake and real)
|
||||
default: false
|
||||
authme.admin.setspawn:
|
||||
description: Set the AuthMe spawn point
|
||||
default: false
|
||||
authme.admin.spawn:
|
||||
description: Teleport to AuthMe spawn point
|
||||
default: false
|
||||
authme.admin.setfirstspawn:
|
||||
description: Set the AuthMe First Spawn Point
|
||||
default: false
|
||||
authme.admin.firstspawn:
|
||||
description: Teleport to AuthMe First Spawn Point
|
||||
default: false
|
||||
authme.admin.switchantibot:
|
||||
description: Switch AntiBot mode on/off
|
||||
default: false
|
||||
authme.admin.purge:
|
||||
description: Database purge command
|
||||
default: false
|
||||
authme.admin.purgebannedplayers:
|
||||
description: Purge banned players
|
||||
default: false
|
||||
authme.admin.purgelastpos:
|
||||
description: Purge last position of a player/players
|
||||
default: false
|
||||
authme.admin.converter:
|
||||
description: Allow the /authme converter command
|
||||
default: false
|
||||
authme.admin.reload:
|
||||
description: Reload the plugin
|
||||
default: false
|
||||
authme.vip:
|
||||
description: Allow vip slot when the server is full
|
||||
default: false
|
||||
authme.bypassantibot:
|
||||
description: Bypass the AntiBot check
|
||||
default: false
|
||||
authme.allowmultipleaccounts:
|
||||
description: Allow more accounts for same ip
|
||||
default: false
|
||||
authme.bypassforcesurvival:
|
||||
description: Bypass all ForceSurvival features
|
||||
default: false
|
|
@ -2,7 +2,6 @@ package fr.xephi.authme;
|
|||
|
||||
import ch.jalu.injector.Injector;
|
||||
import ch.jalu.injector.InjectorBuilder;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||
import fr.xephi.authme.command.CommandHandler;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
|
@ -32,6 +31,7 @@ import fr.xephi.authme.settings.properties.SecuritySettings;
|
|||
import fr.xephi.authme.task.CleanupTask;
|
||||
import fr.xephi.authme.task.purge.PurgeService;
|
||||
import fr.xephi.authme.util.ExceptionUtils;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
@ -40,6 +40,7 @@ import org.bukkit.plugin.PluginManager;
|
|||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -79,7 +80,6 @@ public class AuthMe extends JavaPlugin {
|
|||
/*
|
||||
* Constructor for unit testing.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
AuthMe(JavaPluginLoader loader, PluginDescriptionFile description, File dataFolder, File file) {
|
||||
super(loader, description, dataFolder, file);
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ public class AuthMe extends JavaPlugin {
|
|||
*
|
||||
* @return The plugin's name.
|
||||
*/
|
||||
@NotNull
|
||||
public static String getPluginName() {
|
||||
return PLUGIN_NAME;
|
||||
}
|
||||
|
@ -98,6 +99,7 @@ public class AuthMe extends JavaPlugin {
|
|||
*
|
||||
* @return The plugin's version.
|
||||
*/
|
||||
@NotNull
|
||||
public static String getPluginVersion() {
|
||||
return pluginVersion;
|
||||
}
|
||||
|
@ -107,6 +109,7 @@ public class AuthMe extends JavaPlugin {
|
|||
*
|
||||
* @return The plugin's build number.
|
||||
*/
|
||||
@NotNull
|
||||
public static String getPluginBuildNumber() {
|
||||
return pluginBuildNumber;
|
||||
}
|
||||
|
@ -182,7 +185,7 @@ public class AuthMe extends JavaPlugin {
|
|||
*
|
||||
* @param versionRaw the version as given by the plugin description file
|
||||
*/
|
||||
private static void loadPluginInfo(String versionRaw) {
|
||||
private static void loadPluginInfo(@NotNull String versionRaw) {
|
||||
int index = versionRaw.lastIndexOf("-");
|
||||
if (index != -1) {
|
||||
pluginVersion = versionRaw.substring(0, index);
|
||||
|
@ -198,7 +201,7 @@ public class AuthMe extends JavaPlugin {
|
|||
*/
|
||||
private void initialize() {
|
||||
// Create plugin folder
|
||||
getDataFolder().mkdir();
|
||||
FileUtils.createDirectoryOrFail(getDataFolder());
|
||||
|
||||
// Create injector, provide elements from the Bukkit environment and register providers
|
||||
injector = new InjectorBuilder()
|
||||
|
@ -241,7 +244,7 @@ public class AuthMe extends JavaPlugin {
|
|||
*
|
||||
* @param injector the injector
|
||||
*/
|
||||
void instantiateServices(Injector injector) {
|
||||
void instantiateServices(@NotNull Injector injector) {
|
||||
database = injector.getSingleton(DataSource.class);
|
||||
bukkitService = injector.getSingleton(BukkitService.class);
|
||||
commandHandler = injector.getSingleton(CommandHandler.class);
|
||||
|
@ -259,7 +262,7 @@ public class AuthMe extends JavaPlugin {
|
|||
*
|
||||
* @param injector the injector
|
||||
*/
|
||||
void registerEventListeners(Injector injector) {
|
||||
void registerEventListeners(@NotNull Injector injector) {
|
||||
// Get the plugin manager instance
|
||||
PluginManager pluginManager = getServer().getPluginManager();
|
||||
|
||||
|
@ -332,8 +335,8 @@ public class AuthMe extends JavaPlugin {
|
|||
* @return True if the command was executed, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd,
|
||||
String commandLabel, String[] args) {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd,
|
||||
@NotNull String commandLabel, String[] args) {
|
||||
// Make sure the command handler has been initialized
|
||||
if (commandHandler == null) {
|
||||
getLogger().severe("AuthMe command handler is not available");
|
||||
|
@ -344,6 +347,7 @@ public class AuthMe extends JavaPlugin {
|
|||
return commandHandler.processCommand(sender, commandLabel, args);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getServerNameVersionSafe() {
|
||||
try {
|
||||
Server server = getServer();
|
||||
|
@ -352,4 +356,5 @@ public class AuthMe extends JavaPlugin {
|
|||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package fr.xephi.authme;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import fr.xephi.authme.output.LogLevel;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.util.ExceptionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
|
@ -42,7 +42,9 @@ public final class ConsoleLogger {
|
|||
private static OutputStreamWriter fileWriter;
|
||||
|
||||
// Individual state
|
||||
@NotNull
|
||||
private final String name;
|
||||
@NotNull
|
||||
private LogLevel logLevel = LogLevel.INFO;
|
||||
|
||||
/**
|
||||
|
@ -50,7 +52,7 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param name the name of this logger (the fully qualified class name using it)
|
||||
*/
|
||||
public ConsoleLogger(String name) {
|
||||
public ConsoleLogger(@NotNull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
@ -58,7 +60,7 @@ public final class ConsoleLogger {
|
|||
// Configurations
|
||||
// --------
|
||||
|
||||
public static void initialize(Logger logger, File logFile) {
|
||||
public static void initialize(@NotNull Logger logger, @NotNull File logFile) {
|
||||
ConsoleLogger.logger = logger;
|
||||
ConsoleLogger.logFile = logFile;
|
||||
}
|
||||
|
@ -68,7 +70,7 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param settings the settings to read from
|
||||
*/
|
||||
public static void initializeSharedSettings(Settings settings) {
|
||||
public static void initializeSharedSettings(@NotNull Settings settings) {
|
||||
boolean useLogging = settings.getProperty(SecuritySettings.USE_LOGGING);
|
||||
if (useLogging) {
|
||||
initializeFileWriter();
|
||||
|
@ -82,14 +84,16 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param settings the settings to read from
|
||||
*/
|
||||
public void initializeSettings(Settings settings) {
|
||||
public void initializeSettings(@NotNull Settings settings) {
|
||||
this.logLevel = settings.getProperty(PluginSettings.LOG_LEVEL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public LogLevel getLogLevel() {
|
||||
return logLevel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -104,8 +108,12 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
public void warning(String message) {
|
||||
logger.warning(message);
|
||||
public void warning(@NotNull String message) {
|
||||
if (logger != null) {
|
||||
logger.warning(message);
|
||||
} else {
|
||||
System.err.println("[WARN] " + message);
|
||||
}
|
||||
writeLog("[WARN] " + message);
|
||||
}
|
||||
|
||||
|
@ -116,9 +124,9 @@ public final class ConsoleLogger {
|
|||
* @param message The message to accompany the exception
|
||||
* @param th The Throwable to log
|
||||
*/
|
||||
public void logException(String message, Throwable th) {
|
||||
public void logException(@NotNull String message, @NotNull Throwable th) {
|
||||
warning(message + " " + ExceptionUtils.formatException(th));
|
||||
writeLog(Throwables.getStackTraceAsString(th));
|
||||
writeLog(ExceptionUtils.getStackTraceAsString(th));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,8 +134,12 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
public void info(String message) {
|
||||
logger.info(message);
|
||||
public void info(@NotNull String message) {
|
||||
if (logger != null) {
|
||||
logger.info(message);
|
||||
} else {
|
||||
System.out.println("[INFO] " + message);
|
||||
}
|
||||
writeLog("[INFO] " + message);
|
||||
}
|
||||
|
||||
|
@ -139,9 +151,13 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
public void fine(String message) {
|
||||
public void fine(@NotNull String message) {
|
||||
if (logLevel.includes(LogLevel.FINE)) {
|
||||
logger.info(message);
|
||||
if (logger != null) {
|
||||
logger.info(message);
|
||||
} else {
|
||||
System.err.println("[FINE] " + message);
|
||||
}
|
||||
writeLog("[FINE] " + message);
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +174,7 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to log
|
||||
*/
|
||||
public void debug(String message) {
|
||||
public void debug(@NotNull String message) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
logAndWriteWithDebugPrefix(message);
|
||||
}
|
||||
|
@ -171,7 +187,7 @@ public final class ConsoleLogger {
|
|||
* @param param1 parameter to replace in the message
|
||||
*/
|
||||
// Avoids array creation if DEBUG level is disabled
|
||||
public void debug(String message, Object param1) {
|
||||
public void debug(@NotNull String message, Object param1) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
debug(message, new Object[]{param1});
|
||||
}
|
||||
|
@ -185,7 +201,7 @@ public final class ConsoleLogger {
|
|||
* @param param2 second param to replace in message
|
||||
*/
|
||||
// Avoids array creation if DEBUG level is disabled
|
||||
public void debug(String message, Object param1, Object param2) {
|
||||
public void debug(@NotNull String message, Object param1, Object param2) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
debug(message, new Object[]{param1, param2});
|
||||
}
|
||||
|
@ -197,7 +213,7 @@ public final class ConsoleLogger {
|
|||
* @param message the message
|
||||
* @param params the params to replace in the message
|
||||
*/
|
||||
public void debug(String message, Object... params) {
|
||||
public void debug(@NotNull String message, Object... params) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
logAndWriteWithDebugPrefix(MessageFormat.format(message, params));
|
||||
}
|
||||
|
@ -208,15 +224,19 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param msgSupplier the message supplier
|
||||
*/
|
||||
public void debug(Supplier<String> msgSupplier) {
|
||||
public void debug(@NotNull Supplier<String> msgSupplier) {
|
||||
if (logLevel.includes(LogLevel.DEBUG)) {
|
||||
logAndWriteWithDebugPrefix(msgSupplier.get());
|
||||
}
|
||||
}
|
||||
|
||||
private void logAndWriteWithDebugPrefix(String message) {
|
||||
private void logAndWriteWithDebugPrefix(@NotNull String message) {
|
||||
String debugMessage = "[DEBUG] " + message;
|
||||
logger.info(debugMessage);
|
||||
if (logger != null) {
|
||||
logger.info(debugMessage);
|
||||
} else {
|
||||
System.err.println(debugMessage);
|
||||
}
|
||||
writeLog(debugMessage);
|
||||
}
|
||||
|
||||
|
@ -244,7 +264,7 @@ public final class ConsoleLogger {
|
|||
*
|
||||
* @param message The message to write to the log
|
||||
*/
|
||||
private static void writeLog(String message) {
|
||||
private static void writeLog(@NotNull String message) {
|
||||
if (fileWriter != null) {
|
||||
String dateTime = DATE_FORMAT.format(LocalDateTime.now());
|
||||
try {
|
||||
|
@ -284,4 +304,5 @@ public final class ConsoleLogger {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -445,7 +445,7 @@ public class CommandInitializer {
|
|||
.labels("converter", "convert", "conv")
|
||||
.description("Converter command")
|
||||
.detailedDescription("Converter command for AuthMeReloaded.")
|
||||
.withArgument("job", "Conversion job: xauth / crazylogin / rakamak / "
|
||||
.withArgument("job", "Conversion job: crazylogin / rakamak / "
|
||||
+ "royalauth / vauth / sqliteToSql / mysqlToSqlite / loginsecurity", OPTIONAL)
|
||||
.permission(AdminPermission.CONVERTER)
|
||||
.executableCommand(ConverterCommand.class)
|
||||
|
|
|
@ -13,7 +13,6 @@ import fr.xephi.authme.datasource.converter.RakamakConverter;
|
|||
import fr.xephi.authme.datasource.converter.RoyalAuthConverter;
|
||||
import fr.xephi.authme.datasource.converter.SqliteToSql;
|
||||
import fr.xephi.authme.datasource.converter.VAuthConverter;
|
||||
import fr.xephi.authme.datasource.converter.XAuthConverter;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
|
@ -81,7 +80,6 @@ public class ConverterCommand implements ExecutableCommand {
|
|||
*/
|
||||
private static Map<String, Class<? extends Converter>> getConverters() {
|
||||
return ImmutableSortedMap.<String, Class<? extends Converter>>naturalOrder()
|
||||
.put("xauth", XAuthConverter.class)
|
||||
.put("crazylogin", CrazyLoginConverter.class)
|
||||
.put("rakamak", RakamakConverter.class)
|
||||
.put("royalauth", RoyalAuthConverter.class)
|
||||
|
|
|
@ -25,7 +25,7 @@ public class GetIpCommand implements ExecutableCommand {
|
|||
Player player = bukkitService.getPlayerExact(playerName);
|
||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||
|
||||
if (player != null) {
|
||||
if (player != null && player.getAddress() != null) {
|
||||
sender.sendMessage("Current IP of " + player.getName() + " is " + PlayerUtils.getPlayerIp(player)
|
||||
+ ":" + player.getAddress().getPort());
|
||||
}
|
||||
|
|
|
@ -29,9 +29,12 @@ public class PurgeBannedPlayersCommand implements ExecutableCommand {
|
|||
Set<OfflinePlayer> bannedPlayers = bukkitService.getBannedPlayers();
|
||||
Set<String> namedBanned = new HashSet<>(bannedPlayers.size());
|
||||
for (OfflinePlayer offlinePlayer : bannedPlayers) {
|
||||
if (offlinePlayer.getName() == null) {
|
||||
continue;
|
||||
}
|
||||
namedBanned.add(offlinePlayer.getName().toLowerCase());
|
||||
}
|
||||
|
||||
purgeService.purgePlayers(sender, namedBanned, bannedPlayers.toArray(new OfflinePlayer[bannedPlayers.size()]));
|
||||
purgeService.purgePlayers(sender, namedBanned, bannedPlayers.toArray(new OfflinePlayer[0]));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,10 @@ public class PurgeCommand implements ExecutableCommand {
|
|||
String daysStr = arguments.get(0);
|
||||
|
||||
// Convert the days string to an integer value, and make sure it's valid
|
||||
Integer days = Ints.tryParse(daysStr);
|
||||
if (days == null) {
|
||||
int days;
|
||||
try {
|
||||
days = Integer.parseInt(daysStr);
|
||||
} catch (NumberFormatException e) {
|
||||
sender.sendMessage(ChatColor.RED + "The value you've entered is invalid!");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -61,12 +61,8 @@ class HasPermissionChecker implements DebugSection {
|
|||
Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player == null) {
|
||||
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(playerName);
|
||||
if (offlinePlayer == null) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Player '" + playerName + "' does not exist");
|
||||
} else {
|
||||
sender.sendMessage("Player '" + playerName + "' not online; checking with offline player");
|
||||
performPermissionCheck(offlinePlayer, permissionNode, permissionsManager::hasPermissionOffline, sender);
|
||||
}
|
||||
sender.sendMessage("Player '" + playerName + "' not online; checking with offline player");
|
||||
performPermissionCheck(offlinePlayer, permissionNode, permissionsManager::hasPermissionOffline, sender);
|
||||
} else {
|
||||
performPermissionCheck(player, permissionNode, permissionsManager::hasPermission, sender);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ public class PlayerAuth {
|
|||
}
|
||||
|
||||
public void setQuitLocation(Location location) {
|
||||
Objects.requireNonNull(location.getWorld(), "world not loaded!");
|
||||
x = location.getBlockX();
|
||||
y = location.getBlockY();
|
||||
z = location.getBlockZ();
|
||||
|
@ -300,6 +301,7 @@ public class PlayerAuth {
|
|||
* @return this builder instance
|
||||
*/
|
||||
public Builder location(Location location) {
|
||||
Objects.requireNonNull(location.getWorld(), "world not loaded!");
|
||||
this.x = location.getX();
|
||||
this.y = location.getY();
|
||||
this.z = location.getZ();
|
||||
|
|
|
@ -66,6 +66,7 @@ class LimboPlayerTaskManager {
|
|||
*/
|
||||
void registerTimeoutTask(Player player, LimboPlayer limbo) {
|
||||
final int timeout = settings.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||
//noinspection ConstantConditions Inspection error!
|
||||
if (timeout > 0) {
|
||||
String message = messages.retrieveSingle(player, MessageKey.LOGIN_TIMEOUT_ERROR);
|
||||
BukkitTask task = bukkitService.runTaskLater(new TimeoutTask(player, message, playerCache), timeout);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package fr.xephi.authme.data.limbo.persistence;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
@ -19,6 +18,7 @@ import java.io.File;
|
|||
import java.io.FileWriter;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
@ -115,7 +115,7 @@ class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
}
|
||||
|
||||
try {
|
||||
return gson.fromJson(Files.asCharSource(file, StandardCharsets.UTF_8).read(), LIMBO_MAP_TYPE);
|
||||
return gson.fromJson(new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8), LIMBO_MAP_TYPE);
|
||||
} catch (Exception e) {
|
||||
logger.logException("Failed reading '" + file + "':", e);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package fr.xephi.authme.data.limbo.persistence;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
|
@ -15,6 +14,7 @@ import javax.inject.Inject;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Saves LimboPlayer objects as JSON into individual files.
|
||||
|
@ -48,7 +48,7 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
}
|
||||
|
||||
try {
|
||||
String str = Files.asCharSource(file, StandardCharsets.UTF_8).read();
|
||||
String str = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
|
||||
return gson.fromJson(str, LimboPlayer.class);
|
||||
} catch (IOException e) {
|
||||
logger.logException("Could not read player data on disk for '" + player.getName() + "'", e);
|
||||
|
@ -61,9 +61,8 @@ class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
|
|||
String id = player.getUniqueId().toString();
|
||||
try {
|
||||
File file = new File(cacheDir, id + File.separator + "data.json");
|
||||
Files.createParentDirs(file);
|
||||
Files.touch(file);
|
||||
Files.write(gson.toJson(limboPlayer), file, StandardCharsets.UTF_8);
|
||||
FileUtils.createDirectoryOrFail(file);
|
||||
Files.write(file.toPath(), gson.toJson(limboPlayer).getBytes(StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
logger.logException("Failed to write " + player.getName() + " data:", e);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import fr.xephi.authme.data.limbo.LimboPlayer;
|
|||
import org.bukkit.Location;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Converts a LimboPlayer to a JsonElement.
|
||||
|
@ -36,7 +37,7 @@ class LimboPlayerSerializer implements JsonSerializer<LimboPlayer> {
|
|||
public JsonElement serialize(LimboPlayer limboPlayer, Type type, JsonSerializationContext context) {
|
||||
Location loc = limboPlayer.getLocation();
|
||||
JsonObject locationObject = new JsonObject();
|
||||
locationObject.addProperty(LOC_WORLD, loc.getWorld().getName());
|
||||
locationObject.addProperty(LOC_WORLD, Objects.requireNonNull(loc.getWorld()).getName());
|
||||
locationObject.addProperty(LOC_X, loc.getX());
|
||||
locationObject.addProperty(LOC_Y, loc.getY());
|
||||
locationObject.addProperty(LOC_Z, loc.getZ());
|
||||
|
|
|
@ -18,6 +18,7 @@ import fr.xephi.authme.util.Utils;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
|
@ -65,8 +66,8 @@ public class CacheDataSource implements DataSource {
|
|||
});
|
||||
}
|
||||
|
||||
public LoadingCache<String, Optional<PlayerAuth>> getCachedAuths() {
|
||||
return cachedAuths;
|
||||
public Map<String, Optional<PlayerAuth>> getCachedAuths() {
|
||||
return cachedAuths.asMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -292,8 +293,10 @@ public class CacheDataSource implements DataSource {
|
|||
cachedAuths.invalidate(playerName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("OptionalAssignedToNull")
|
||||
@Override
|
||||
public void refreshCache(String playerName) {
|
||||
// We are actually checking if the entry is cached
|
||||
if (cachedAuths.getIfPresent(playerName) != null) {
|
||||
cachedAuths.refresh(playerName);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package fr.xephi.authme.datasource;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
|
@ -10,6 +9,8 @@ import fr.xephi.authme.util.FileUtils;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
|
@ -72,7 +73,7 @@ class SqLiteMigrater {
|
|||
String backupName = "backup-" + databaseName + FileUtils.createCurrentTimeString() + ".db";
|
||||
File backup = new File(backupDirectory, backupName);
|
||||
try {
|
||||
Files.copy(sqLite, backup);
|
||||
Files.copy(sqLite.toPath(), backup.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
return backupName;
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to create SQLite backup before migration", e);
|
||||
|
|
|
@ -34,6 +34,9 @@ public class RoyalAuthConverter implements Converter {
|
|||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
for (OfflinePlayer player : plugin.getServer().getOfflinePlayers()) {
|
||||
if (player.getName() == null) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
String name = player.getName().toLowerCase();
|
||||
File file = new File(makePath(".", "plugins", "RoyalAuth", "userdata", name + ".yml"));
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
package fr.xephi.authme.datasource.converter;
|
||||
|
||||
import de.luricos.bukkit.xAuth.database.DatabaseTables;
|
||||
import de.luricos.bukkit.xAuth.utils.xAuthLog;
|
||||
import de.luricos.bukkit.xAuth.xAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.util.FileUtils.makePath;
|
||||
|
||||
public class XAuthConverter implements Converter {
|
||||
|
||||
@Inject
|
||||
@DataFolder
|
||||
private File dataFolder;
|
||||
@Inject
|
||||
private DataSource database;
|
||||
@Inject
|
||||
private PluginManager pluginManager;
|
||||
|
||||
XAuthConverter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender sender) {
|
||||
try {
|
||||
Class.forName("de.luricos.bukkit.xAuth.xAuth");
|
||||
convert(sender);
|
||||
} catch (ClassNotFoundException ce) {
|
||||
sender.sendMessage("xAuth has not been found, please put xAuth.jar in your plugin folder and restart!");
|
||||
}
|
||||
}
|
||||
|
||||
private void convert(CommandSender sender) {
|
||||
if (pluginManager.getPlugin("xAuth") == null) {
|
||||
sender.sendMessage("[AuthMe] xAuth plugin not found");
|
||||
return;
|
||||
}
|
||||
//TODO ljacqu 20160702: xAuthDb is not used except for the existence check -- is this intended?
|
||||
File xAuthDb = new File(dataFolder.getParent(), makePath("xAuth", "xAuth.h2.db"));
|
||||
if (!xAuthDb.exists()) {
|
||||
sender.sendMessage("[AuthMe] xAuth H2 database not found, checking for MySQL or SQLite data...");
|
||||
}
|
||||
List<Integer> players = getXAuthPlayers();
|
||||
if (Utils.isCollectionEmpty(players)) {
|
||||
sender.sendMessage("[AuthMe] Error while importing xAuthPlayers: did not find any players");
|
||||
return;
|
||||
}
|
||||
sender.sendMessage("[AuthMe] Starting import...");
|
||||
|
||||
for (int id : players) {
|
||||
String pl = getIdPlayer(id);
|
||||
String psw = getPassword(id);
|
||||
if (psw != null && !psw.isEmpty() && pl != null) {
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(pl.toLowerCase())
|
||||
.realName(pl)
|
||||
.password(psw, null).build();
|
||||
database.saveAuth(auth);
|
||||
}
|
||||
}
|
||||
sender.sendMessage("[AuthMe] Successfully converted from xAuth database");
|
||||
}
|
||||
|
||||
private String getIdPlayer(int id) {
|
||||
String realPass = "";
|
||||
Connection conn = xAuth.getPlugin().getDatabaseController().getConnection();
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = String.format("SELECT `playername` FROM `%s` WHERE `id` = ?",
|
||||
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
||||
ps = conn.prepareStatement(sql);
|
||||
ps.setInt(1, id);
|
||||
rs = ps.executeQuery();
|
||||
if (!rs.next()) {
|
||||
return null;
|
||||
}
|
||||
realPass = rs.getString("playername").toLowerCase();
|
||||
} catch (SQLException e) {
|
||||
xAuthLog.severe("Failed to retrieve name for account: " + id, e);
|
||||
return null;
|
||||
} finally {
|
||||
xAuth.getPlugin().getDatabaseController().close(conn, ps, rs);
|
||||
}
|
||||
return realPass;
|
||||
}
|
||||
|
||||
private List<Integer> getXAuthPlayers() {
|
||||
List<Integer> xP = new ArrayList<>();
|
||||
Connection conn = xAuth.getPlugin().getDatabaseController().getConnection();
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = String.format("SELECT * FROM `%s`",
|
||||
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
||||
ps = conn.prepareStatement(sql);
|
||||
rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
xP.add(rs.getInt("id"));
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
xAuthLog.severe("Cannot import xAuthPlayers", e);
|
||||
return new ArrayList<>();
|
||||
} finally {
|
||||
xAuth.getPlugin().getDatabaseController().close(conn, ps, rs);
|
||||
}
|
||||
return xP;
|
||||
}
|
||||
|
||||
private String getPassword(int accountId) {
|
||||
String realPass = "";
|
||||
Connection conn = xAuth.getPlugin().getDatabaseController().getConnection();
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = String.format("SELECT `password`, `pwtype` FROM `%s` WHERE `id` = ?",
|
||||
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
||||
ps = conn.prepareStatement(sql);
|
||||
ps.setInt(1, accountId);
|
||||
rs = ps.executeQuery();
|
||||
if (!rs.next()) {
|
||||
return null;
|
||||
}
|
||||
realPass = rs.getString("password");
|
||||
} catch (SQLException e) {
|
||||
xAuthLog.severe("Failed to retrieve password hash for account: " + accountId, e);
|
||||
return null;
|
||||
} finally {
|
||||
xAuth.getPlugin().getDatabaseController().close(conn, ps, rs);
|
||||
}
|
||||
return realPass;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.events;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is called when a player uses the login command,
|
||||
|
@ -63,6 +64,7 @@ public class AuthMeAsyncPreLoginEvent extends CustomEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.events;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is called when a player uses the register command,
|
||||
|
@ -63,6 +64,7 @@ public class AuthMeAsyncPreRegisterEvent extends CustomEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bukkit.Location;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is fired before AuthMe teleports a player for general purposes.
|
||||
|
@ -32,6 +33,7 @@ public class AuthMeTeleportEvent extends AbstractTeleportEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is called when a player adds or changes his email address.
|
||||
|
@ -70,6 +71,7 @@ public class EmailChangedEvent extends CustomEvent implements Cancellable {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.events;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Event fired when a player enters a wrong password.
|
||||
|
@ -40,6 +41,7 @@ public class FailedLoginEvent extends CustomEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bukkit.Location;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Event that is called if a player is teleported to the AuthMe first spawn, i.e. to the
|
||||
|
@ -33,6 +34,7 @@ public class FirstSpawnTeleportEvent extends AbstractTeleportEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.events;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Event fired when a player has successfully logged in or registered.
|
||||
|
@ -51,6 +52,7 @@ public class LoginEvent extends CustomEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.events;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is called when a player logs out through AuthMe, i.e. only when the player
|
||||
|
@ -42,6 +43,7 @@ public class LogoutEvent extends CustomEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package fr.xephi.authme.events;
|
|||
|
||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is called when we need to compare or hash a password for a player and allows
|
||||
|
@ -23,20 +24,6 @@ public class PasswordEncryptionEvent extends CustomEvent {
|
|||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link org.bukkit.event.Event}.
|
||||
*
|
||||
* @return The list of handlers
|
||||
*/
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the encryption method used to hash the password.
|
||||
*
|
||||
|
@ -54,4 +41,20 @@ public class PasswordEncryptionEvent extends CustomEvent {
|
|||
public void setMethod(EncryptionMethod method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of handlers, equivalent to {@link #getHandlers()} and required by {@link org.bukkit.event.Event}.
|
||||
*
|
||||
* @return The list of handlers
|
||||
*/
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.bukkit.event.Cancellable;
|
|||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is called before the inventory data of a player is suppressed,
|
||||
|
@ -78,6 +79,7 @@ public class ProtectInventoryEvent extends CustomEvent implements Cancellable {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.events;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Event fired when a player has successfully registered.
|
||||
|
@ -40,6 +41,7 @@ public class RegisterEvent extends CustomEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bukkit.entity.Player;
|
|||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is fired when the inventory of a player is restored
|
||||
|
@ -53,6 +54,7 @@ public class RestoreInventoryEvent extends CustomEvent implements Cancellable {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.events;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Event fired before a session is restored.
|
||||
|
@ -45,7 +46,9 @@ public class RestoreSessionEvent extends CustomEvent implements Cancellable {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bukkit.Location;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Called if a player is teleported to a specific spawn upon joining or logging in.
|
||||
|
@ -44,6 +45,7 @@ public class SpawnTeleportEvent extends AbstractTeleportEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.events;
|
|||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Event fired after a player has been unregistered from an external source (by an admin or via the API).
|
||||
|
@ -61,7 +62,9 @@ public class UnregisterByAdminEvent extends AbstractUnregisterEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package fr.xephi.authme.events;
|
|||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Event fired after a player has unregistered himself.
|
||||
|
@ -30,7 +31,9 @@ public class UnregisterByPlayerEvent extends AbstractUnregisterEvent {
|
|||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ public class PlayerListener implements Listener {
|
|||
final String name = event.getName();
|
||||
|
||||
// NOTE: getAddress() sometimes returning null, we don't want to handle this race condition
|
||||
//noinspection ConstantConditions
|
||||
if (event.getAddress() == null) {
|
||||
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER,
|
||||
messages.retrieveSingle(name, MessageKey.KICK_UNRESOLVED_HOSTNAME));
|
||||
|
|
|
@ -7,7 +7,6 @@ import ch.jalu.configme.properties.StringProperty;
|
|||
import ch.jalu.configme.resource.PropertyReader;
|
||||
import ch.jalu.configme.resource.PropertyResource;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
|
@ -15,6 +14,8 @@ import fr.xephi.authme.util.FileUtils;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
@ -30,7 +31,7 @@ import static java.util.Collections.singletonList;
|
|||
*/
|
||||
public class MessageUpdater {
|
||||
|
||||
private ConsoleLogger logger = ConsoleLoggerFactory.get(MessageUpdater.class);
|
||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(MessageUpdater.class);
|
||||
|
||||
/**
|
||||
* Applies any necessary migrations to the user's messages file and saves it if it has been modified.
|
||||
|
@ -120,7 +121,7 @@ public class MessageUpdater {
|
|||
String backupName = FileUtils.createBackupFilePath(messagesFile);
|
||||
File backupFile = new File(backupName);
|
||||
try {
|
||||
Files.copy(messagesFile, backupFile);
|
||||
Files.copy(messagesFile.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Could not back up '" + messagesFile + "' to '" + backupFile + "'", e);
|
||||
}
|
||||
|
@ -166,7 +167,7 @@ public class MessageUpdater {
|
|||
|
||||
// Create ConfigurationData instance
|
||||
Map<String, List<String>> commentsMap = comments.entrySet().stream()
|
||||
.collect(Collectors.toMap(e -> e.getKey(), e -> singletonList(e.getValue())));
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> singletonList(e.getValue())));
|
||||
return new MessageKeyConfigurationData(builder, commentsMap);
|
||||
}
|
||||
|
||||
|
@ -184,13 +185,13 @@ public class MessageUpdater {
|
|||
|
||||
static final class MessageKeyPropertyListBuilder {
|
||||
|
||||
private PropertyListBuilder propertyListBuilder = new PropertyListBuilder();
|
||||
private final PropertyListBuilder propertyListBuilder = new PropertyListBuilder();
|
||||
|
||||
void addMessageKey(MessageKey key) {
|
||||
propertyListBuilder.add(new MessageKeyProperty(key));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
List<MessageKeyProperty> getAllProperties() {
|
||||
return (List) propertyListBuilder.create();
|
||||
}
|
||||
|
|
|
@ -42,12 +42,7 @@ public class VaultHandler implements PermissionHandler {
|
|||
throw new PermissionHandlerException("Could not load permissions provider service");
|
||||
}
|
||||
|
||||
// Get the Vault provider and make sure it's valid
|
||||
Permission vaultPerms = permissionProvider.getProvider();
|
||||
if (vaultPerms == null) {
|
||||
throw new PermissionHandlerException("Could not load Vault permissions provider");
|
||||
}
|
||||
return vaultPerms;
|
||||
return permissionProvider.getProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -130,9 +130,8 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||
return;
|
||||
}
|
||||
} else if (!service.getProperty(RegistrationSettings.FORCE)) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() -> {
|
||||
welcomeMessageConfiguration.sendWelcomeMessage(player);
|
||||
});
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() ->
|
||||
welcomeMessageConfiguration.sendWelcomeMessage(player));
|
||||
|
||||
// Skip if registration is optional
|
||||
return;
|
||||
|
@ -169,6 +168,7 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||
}
|
||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||
// Allow infinite blindness effect
|
||||
//noinspection ConstantConditions Inspection error!
|
||||
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
|
||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ public enum HashAlgorithm {
|
|||
WBB3(fr.xephi.authme.security.crypts.Wbb3.class),
|
||||
WBB4(fr.xephi.authme.security.crypts.Wbb4.class),
|
||||
WORDPRESS(fr.xephi.authme.security.crypts.Wordpress.class),
|
||||
XAUTH(fr.xephi.authme.security.crypts.XAuth.class),
|
||||
XFBCRYPT(fr.xephi.authme.security.crypts.XfBCrypt.class),
|
||||
CUSTOM(null),
|
||||
|
||||
|
@ -38,8 +37,7 @@ public enum HashAlgorithm {
|
|||
@Deprecated MD5(fr.xephi.authme.security.crypts.Md5.class),
|
||||
@Deprecated PLAINTEXT(null),
|
||||
@Deprecated SHA1(fr.xephi.authme.security.crypts.Sha1.class),
|
||||
@Deprecated SHA512(fr.xephi.authme.security.crypts.Sha512.class),
|
||||
@Deprecated WHIRLPOOL(fr.xephi.authme.security.crypts.Whirlpool.class);
|
||||
@Deprecated SHA512(fr.xephi.authme.security.crypts.Sha512.class);
|
||||
|
||||
private final Class<? extends EncryptionMethod> clazz;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public final class HashUtils {
|
|||
* @return True if the salt is valid, false otherwise
|
||||
*/
|
||||
public static boolean isValidBcryptHash(String hash) {
|
||||
return hash.length() == 60 && hash.substring(0, 2).equals("$2");
|
||||
return hash.length() == 60 && hash.startsWith("$2");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -148,6 +148,7 @@ public class PasswordSecurity implements Reloadable {
|
|||
*
|
||||
* @return The associated encryption method, or null if CUSTOM / deprecated
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private EncryptionMethod initializeEncryptionMethod(HashAlgorithm algorithm) {
|
||||
if (HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)) {
|
||||
return null;
|
||||
|
|
|
@ -41,8 +41,11 @@ public class Pbkdf2 extends HexSaltedMethod {
|
|||
if (line.length != 4) {
|
||||
return false;
|
||||
}
|
||||
Integer iterations = Ints.tryParse(line[1]);
|
||||
if (iterations == null) {
|
||||
|
||||
int iterations;
|
||||
try {
|
||||
iterations = Integer.parseInt(line[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warning("Cannot read number of rounds for Pbkdf2: '" + line[1] + "'");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -30,8 +30,11 @@ public class Pbkdf2Django extends HexSaltedMethod {
|
|||
if (line.length != 4) {
|
||||
return false;
|
||||
}
|
||||
Integer iterations = Ints.tryParse(line[1]);
|
||||
if (iterations == null) {
|
||||
|
||||
int iterations;
|
||||
try {
|
||||
iterations = Integer.parseInt(line[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warning("Cannot read number of rounds for Pbkdf2Django: '" + line[1] + "'");
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import fr.xephi.authme.security.crypts.description.SaltType;
|
|||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
import static fr.xephi.authme.security.HashUtils.isEqual;
|
||||
|
@ -72,14 +73,10 @@ public class PhpBB implements EncryptionMethod {
|
|||
private static final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
private static String md5(String data) {
|
||||
try {
|
||||
byte[] bytes = data.getBytes("ISO-8859-1");
|
||||
MessageDigest md5er = HashUtils.getDigest(MessageDigestAlgorithm.MD5);
|
||||
byte[] hash = md5er.digest(bytes);
|
||||
return bytes2hex(hash);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedOperationException(e);
|
||||
}
|
||||
byte[] bytes = data.getBytes(StandardCharsets.ISO_8859_1);
|
||||
MessageDigest md5er = HashUtils.getDigest(MessageDigestAlgorithm.MD5);
|
||||
byte[] hash = md5er.digest(bytes);
|
||||
return bytes2hex(hash);
|
||||
}
|
||||
|
||||
private static int hexToInt(char ch) {
|
||||
|
@ -136,15 +133,13 @@ public class PhpBB implements EncryptionMethod {
|
|||
|
||||
private static String _hash_crypt_private(String password, String setting) {
|
||||
String output = "*";
|
||||
if (!setting.substring(0, 3).equals("$H$"))
|
||||
if (!setting.startsWith("$H$"))
|
||||
return output;
|
||||
int count_log2 = itoa64.indexOf(setting.charAt(3));
|
||||
if (count_log2 < 7 || count_log2 > 30)
|
||||
return output;
|
||||
int count = 1 << count_log2;
|
||||
String salt = setting.substring(4, 12);
|
||||
if (salt.length() != 8)
|
||||
return output;
|
||||
String m1 = md5(salt + password);
|
||||
String hash = pack(m1);
|
||||
do {
|
||||
|
|
|
@ -9,6 +9,7 @@ import fr.xephi.authme.util.RandomStringUtils;
|
|||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
|
@ -21,10 +22,10 @@ public class PhpFusion extends SeparateSaltMethod {
|
|||
String algo = "HmacSHA256";
|
||||
String keyString = HashUtils.sha1(salt);
|
||||
try {
|
||||
SecretKeySpec key = new SecretKeySpec(keyString.getBytes("UTF-8"), algo);
|
||||
SecretKeySpec key = new SecretKeySpec(keyString.getBytes(StandardCharsets.UTF_8), algo);
|
||||
Mac mac = Mac.getInstance(algo);
|
||||
mac.init(key);
|
||||
byte[] bytes = mac.doFinal(password.getBytes("ASCII"));
|
||||
byte[] bytes = mac.doFinal(password.getBytes(StandardCharsets.US_ASCII));
|
||||
StringBuilder hash = new StringBuilder();
|
||||
for (byte aByte : bytes) {
|
||||
String hex = Integer.toHexString(0xFF & aByte);
|
||||
|
@ -34,7 +35,7 @@ public class PhpFusion extends SeparateSaltMethod {
|
|||
hash.append(hex);
|
||||
}
|
||||
return hash.toString();
|
||||
} catch (UnsupportedEncodingException | InvalidKeyException | NoSuchAlgorithmException e) {
|
||||
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
|
||||
throw new UnsupportedOperationException("Cannot create PHPFUSION hash for " + name, e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import com.google.common.escape.Escaper;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.common.net.UrlEscapers;
|
||||
import com.google.common.primitives.Ints;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
|
@ -13,6 +10,9 @@ import fr.xephi.authme.security.crypts.description.Usage;
|
|||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
@ -50,8 +50,15 @@ public class TwoFactor extends UnsaltedMethod {
|
|||
String format = "https://www.google.com/chart?chs=130x130&chld=M%%7C0&cht=qr&chl="
|
||||
+ "otpauth://totp/"
|
||||
+ "%s@%s%%3Fsecret%%3D%s";
|
||||
Escaper urlEscaper = UrlEscapers.urlFragmentEscaper();
|
||||
return String.format(format, urlEscaper.escape(user), urlEscaper.escape(host), secret);
|
||||
|
||||
try {
|
||||
user = URLEncoder.encode(user, StandardCharsets.UTF_8.toString());
|
||||
host = URLEncoder.encode(host, StandardCharsets.UTF_8.toString());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return String.format(format, user, host, secret);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,8 +88,10 @@ public class TwoFactor extends UnsaltedMethod {
|
|||
|
||||
private boolean checkPassword(String secretKey, String userInput)
|
||||
throws NoSuchAlgorithmException, InvalidKeyException {
|
||||
Integer code = Ints.tryParse(userInput);
|
||||
if (code == null) {
|
||||
int code;
|
||||
try {
|
||||
code = Integer.parseInt(userInput);
|
||||
} catch (NumberFormatException e) {
|
||||
//code is not an integer
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,399 +0,0 @@
|
|||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
/**
|
||||
* The Whirlpool hashing function.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <b>References</b>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* The Whirlpool algorithm was developed by <a
|
||||
* href="mailto:pbarreto@scopus.com.br">Paulo S. L. M. Barreto</a> and <a
|
||||
* href="mailto:vincent.rijmen@cryptomathic.com">Vincent Rijmen</a>.
|
||||
* <p/>
|
||||
* See P.S.L.M. Barreto, V. Rijmen, ``The Whirlpool hashing function,'' First
|
||||
* NESSIE workshop, 2000 (tweaked version, 2003),
|
||||
* <https://www.cosic.esat.kuleuven
|
||||
* .ac.be/nessie/workshop/submissions/whirlpool.zip>
|
||||
*
|
||||
* @author Paulo S.L.M. Barreto
|
||||
* @author Vincent Rijmen.
|
||||
* @version 3.0 (2003.03.12)
|
||||
* <p/>
|
||||
* ====================================================================
|
||||
* =========
|
||||
* <p/>
|
||||
* Differences from version 2.1:
|
||||
* <p/>
|
||||
* - Suboptimal diffusion matrix replaced by cir(1, 1, 4, 1, 8, 5, 2,
|
||||
* 9).
|
||||
* <p/>
|
||||
* ====================================================================
|
||||
* =========
|
||||
* <p/>
|
||||
* Differences from version 2.0:
|
||||
* <p/>
|
||||
* - Generation of ISO/IEC 10118-3 test vectors. - Bug fix: nonzero
|
||||
* carry was ignored when tallying the data length (this bug apparently
|
||||
* only manifested itself when feeding data in pieces rather than in a
|
||||
* single chunk at once).
|
||||
* <p/>
|
||||
* Differences from version 1.0:
|
||||
* <p/>
|
||||
* - Original S-box replaced by the tweaked, hardware-efficient
|
||||
* version.
|
||||
* <p/>
|
||||
* ====================================================================
|
||||
* =========
|
||||
* <p/>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Deprecated
|
||||
@Recommendation(Usage.DEPRECATED)
|
||||
public class Whirlpool extends UnsaltedMethod {
|
||||
|
||||
/**
|
||||
* The message digest size (in bits)
|
||||
*/
|
||||
public static final int DIGESTBITS = 512;
|
||||
|
||||
/**
|
||||
* The message digest size (in bytes)
|
||||
*/
|
||||
public static final int DIGESTBYTES = DIGESTBITS >>> 3;
|
||||
|
||||
/**
|
||||
* The number of rounds of the internal dedicated block cipher.
|
||||
*/
|
||||
protected static final int R = 10;
|
||||
|
||||
/**
|
||||
* The substitution box.
|
||||
*/
|
||||
private static final String sbox = "\u1823\uc6E8\u87B8\u014F\u36A6\ud2F5\u796F\u9152" + "\u60Bc\u9B8E\uA30c\u7B35\u1dE0\ud7c2\u2E4B\uFE57" + "\u1577\u37E5\u9FF0\u4AdA\u58c9\u290A\uB1A0\u6B85" + "\uBd5d\u10F4\ucB3E\u0567\uE427\u418B\uA77d\u95d8" + "\uFBEE\u7c66\udd17\u479E\ucA2d\uBF07\uAd5A\u8333" + "\u6302\uAA71\uc819\u49d9\uF2E3\u5B88\u9A26\u32B0" + "\uE90F\ud580\uBEcd\u3448\uFF7A\u905F\u2068\u1AAE" + "\uB454\u9322\u64F1\u7312\u4008\uc3Ec\udBA1\u8d3d" + "\u9700\ucF2B\u7682\ud61B\uB5AF\u6A50\u45F3\u30EF" + "\u3F55\uA2EA\u65BA\u2Fc0\udE1c\uFd4d\u9275\u068A" + "\uB2E6\u0E1F\u62d4\uA896\uF9c5\u2559\u8472\u394c" + "\u5E78\u388c\ud1A5\uE261\uB321\u9c1E\u43c7\uFc04" + "\u5199\u6d0d\uFAdF\u7E24\u3BAB\ucE11\u8F4E\uB7EB" + "\u3c81\u94F7\uB913\u2cd3\uE76E\uc403\u5644\u7FA9" + "\u2ABB\uc153\udc0B\u9d6c\u3174\uF646\uAc89\u14E1" + "\u163A\u6909\u70B6\ud0Ed\ucc42\u98A4\u285c\uF886";
|
||||
|
||||
private static final long[][] C = new long[8][256];
|
||||
private static final long[] rc = new long[R + 1];
|
||||
|
||||
static {
|
||||
for (int x = 0; x < 256; x++) {
|
||||
char c = sbox.charAt(x / 2);
|
||||
long v1 = ((x & 1) == 0) ? c >>> 8 : c & 0xff;
|
||||
long v2 = v1 << 1;
|
||||
if (v2 >= 0x100L) {
|
||||
v2 ^= 0x11dL;
|
||||
}
|
||||
long v4 = v2 << 1;
|
||||
if (v4 >= 0x100L) {
|
||||
v4 ^= 0x11dL;
|
||||
}
|
||||
long v5 = v4 ^ v1;
|
||||
long v8 = v4 << 1;
|
||||
if (v8 >= 0x100L) {
|
||||
v8 ^= 0x11dL;
|
||||
}
|
||||
long v9 = v8 ^ v1;
|
||||
/*
|
||||
* build the circulant table C[0][x] = S[x].[1, 1, 4, 1, 8, 5, 2,
|
||||
* 9]:
|
||||
*/
|
||||
C[0][x] = (v1 << 56) | (v1 << 48) | (v4 << 40) | (v1 << 32) | (v8 << 24) | (v5 << 16) | (v2 << 8) | (v9);
|
||||
/*
|
||||
* build the remaining circulant tables C[t][x] = C[0][x] rotr t
|
||||
*/
|
||||
for (int t = 1; t < 8; t++) {
|
||||
C[t][x] = (C[t - 1][x] >>> 8) | ((C[t - 1][x] << 56));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* build the round constants:
|
||||
*/
|
||||
rc[0] = 0L; /*
|
||||
* not used (assigment kept only to properly initialize all
|
||||
* variables)
|
||||
*/
|
||||
for (int r = 1; r <= R; r++) {
|
||||
int i = 8 * (r - 1);
|
||||
rc[r] = (C[0][i] & 0xff00000000000000L) ^ (C[1][i + 1] & 0x00ff000000000000L) ^ (C[2][i + 2] & 0x0000ff0000000000L) ^ (C[3][i + 3] & 0x000000ff00000000L) ^ (C[4][i + 4] & 0x00000000ff000000L) ^ (C[5][i + 5] & 0x0000000000ff0000L) ^ (C[6][i + 6] & 0x000000000000ff00L) ^ (C[7][i + 7] & 0x00000000000000ffL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Global number of hashed bits (256-bit counter).
|
||||
*/
|
||||
protected final byte[] bitLength = new byte[32];
|
||||
|
||||
/**
|
||||
* Buffer of data to hash.
|
||||
*/
|
||||
protected final byte[] buffer = new byte[64];
|
||||
|
||||
/**
|
||||
* Current number of bits on the buffer.
|
||||
*/
|
||||
protected int bufferBits = 0;
|
||||
|
||||
/**
|
||||
* Current (possibly incomplete) byte slot on the buffer.
|
||||
*/
|
||||
protected int bufferPos = 0;
|
||||
|
||||
/**
|
||||
* The hashing state.
|
||||
*/
|
||||
protected final long[] hash = new long[8];
|
||||
protected final long[] K = new long[8];
|
||||
protected final long[] L = new long[8];
|
||||
protected final long[] block = new long[8];
|
||||
protected final long[] state = new long[8];
|
||||
|
||||
public Whirlpool() {
|
||||
}
|
||||
|
||||
protected static String display(byte[] array) {
|
||||
char[] val = new char[2 * array.length];
|
||||
String hex = "0123456789ABCDEF";
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
int b = array[i] & 0xff;
|
||||
val[2 * i] = hex.charAt(b >>> 4);
|
||||
val[2 * i + 1] = hex.charAt(b & 15);
|
||||
}
|
||||
return String.valueOf(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* The core Whirlpool transform.
|
||||
*/
|
||||
protected void processBuffer() {
|
||||
/*
|
||||
* map the buffer to a block:
|
||||
*/
|
||||
for (int i = 0, j = 0; i < 8; i++, j += 8) {
|
||||
block[i] = (((long) buffer[j]) << 56) ^ (((long) buffer[j + 1] & 0xffL) << 48) ^ (((long) buffer[j + 2] & 0xffL) << 40) ^ (((long) buffer[j + 3] & 0xffL) << 32) ^ (((long) buffer[j + 4] & 0xffL) << 24) ^ (((long) buffer[j + 5] & 0xffL) << 16) ^ (((long) buffer[j + 6] & 0xffL) << 8) ^ (((long) buffer[j + 7] & 0xffL));
|
||||
}
|
||||
/*
|
||||
* compute and apply K^0 to the cipher state:
|
||||
*/
|
||||
for (int i = 0; i < 8; i++) {
|
||||
state[i] = block[i] ^ (K[i] = hash[i]);
|
||||
}
|
||||
/*
|
||||
* iterate over all rounds:
|
||||
*/
|
||||
for (int r = 1; r <= R; r++) {
|
||||
/*
|
||||
* compute K^r from K^{r-1}:
|
||||
*/
|
||||
for (int i = 0; i < 8; i++) {
|
||||
L[i] = 0L;
|
||||
for (int t = 0, s = 56; t < 8; t++, s -= 8) {
|
||||
L[i] ^= C[t][(int) (K[(i - t) & 7] >>> s) & 0xff];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
K[i] = L[i];
|
||||
}
|
||||
K[0] ^= rc[r];
|
||||
/*
|
||||
* apply the r-th round transformation:
|
||||
*/
|
||||
for (int i = 0; i < 8; i++) {
|
||||
L[i] = K[i];
|
||||
for (int t = 0, s = 56; t < 8; t++, s -= 8) {
|
||||
L[i] ^= C[t][(int) (state[(i - t) & 7] >>> s) & 0xff];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
state[i] = L[i];
|
||||
}
|
||||
}
|
||||
/*
|
||||
* apply the Miyaguchi-Preneel compression function:
|
||||
*/
|
||||
for (int i = 0; i < 8; i++) {
|
||||
hash[i] ^= state[i] ^ block[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the hashing state.
|
||||
*/
|
||||
public void NESSIEinit() {
|
||||
Arrays.fill(bitLength, (byte) 0);
|
||||
bufferBits = bufferPos = 0;
|
||||
buffer[0] = 0;
|
||||
Arrays.fill(hash, 0L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers input data to the hashing algorithm.
|
||||
*
|
||||
* @param source plaintext data to hash.
|
||||
* @param sourceBits how many bits of plaintext to process.
|
||||
* <p>
|
||||
* This method maintains the invariant: bufferBits < 512
|
||||
* </p>
|
||||
*/
|
||||
public void NESSIEadd(byte[] source, long sourceBits) {
|
||||
/*
|
||||
* sourcePos | +-------+-------+------- ||||||||||||||||||||| source
|
||||
* +-------+-------+-------
|
||||
* +-------+-------+-------+-------+-------+-------
|
||||
* |||||||||||||||||||||| buffer
|
||||
* +-------+-------+-------+-------+-------+------- | bufferPos
|
||||
*/
|
||||
int sourcePos = 0; // index of leftmost source byte containing data (1
|
||||
// to 8 bits).
|
||||
int sourceGap = (8 - ((int) sourceBits & 7)) & 7; // space on
|
||||
// source[sourcePos].
|
||||
int bufferRem = bufferBits & 7; // occupied bits on buffer[bufferPos].
|
||||
int b;
|
||||
// tally the length of the added data:
|
||||
long value = sourceBits;
|
||||
for (int i = 31, carry = 0; i >= 0; i--) {
|
||||
carry += (bitLength[i] & 0xff) + ((int) value & 0xff);
|
||||
bitLength[i] = (byte) carry;
|
||||
carry >>>= 8;
|
||||
value >>>= 8;
|
||||
}
|
||||
// process data in chunks of 8 bits:
|
||||
while (sourceBits > 8) { // at least source[sourcePos] and
|
||||
// source[sourcePos+1] contain data.
|
||||
// take a byte from the source:
|
||||
b = ((source[sourcePos] << sourceGap) & 0xff) | ((source[sourcePos + 1] & 0xff) >>> (8 - sourceGap));
|
||||
if (b < 0 || b >= 256) {
|
||||
throw new RuntimeException("LOGIC ERROR");
|
||||
}
|
||||
// process this byte:
|
||||
buffer[bufferPos++] |= b >>> bufferRem;
|
||||
bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos;
|
||||
if (bufferBits == 512) {
|
||||
// process data block:
|
||||
processBuffer();
|
||||
// reset buffer:
|
||||
bufferBits = bufferPos = 0;
|
||||
}
|
||||
buffer[bufferPos] = (byte) ((b << (8 - bufferRem)) & 0xff);
|
||||
bufferBits += bufferRem;
|
||||
// proceed to remaining data:
|
||||
sourceBits -= 8;
|
||||
sourcePos++;
|
||||
}
|
||||
// now 0 <= sourceBits <= 8;
|
||||
// furthermore, all data (if any is left) is in source[sourcePos].
|
||||
if (sourceBits > 0) {
|
||||
b = (source[sourcePos] << sourceGap) & 0xff; // bits are
|
||||
// left-justified on b.
|
||||
// process the remaining bits:
|
||||
buffer[bufferPos] |= b >>> bufferRem;
|
||||
} else {
|
||||
b = 0;
|
||||
}
|
||||
if (bufferRem + sourceBits < 8) {
|
||||
// all remaining data fits on buffer[bufferPos], and there still
|
||||
// remains some space.
|
||||
bufferBits += sourceBits;
|
||||
} else {
|
||||
// buffer[bufferPos] is full:
|
||||
bufferPos++;
|
||||
bufferBits += 8 - bufferRem; // bufferBits = 8*bufferPos;
|
||||
sourceBits -= 8 - bufferRem;
|
||||
// now 0 <= sourceBits < 8; furthermore, all data is in
|
||||
// source[sourcePos].
|
||||
if (bufferBits == 512) {
|
||||
// process data block:
|
||||
processBuffer();
|
||||
// reset buffer:
|
||||
bufferBits = bufferPos = 0;
|
||||
}
|
||||
buffer[bufferPos] = (byte) ((b << (8 - bufferRem)) & 0xff);
|
||||
bufferBits += (int) sourceBits;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Get the hash value from the hashing state.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method uses the invariant: bufferBits < 512
|
||||
* </p>
|
||||
* @param digest byte[]
|
||||
*/
|
||||
public void NESSIEfinalize(byte[] digest) {
|
||||
// append a '1'-bit:
|
||||
buffer[bufferPos] |= 0x80 >>> (bufferBits & 7);
|
||||
bufferPos++; // all remaining bits on the current byte are set to zero.
|
||||
// pad with zero bits to complete 512N + 256 bits:
|
||||
if (bufferPos > 32) {
|
||||
while (bufferPos < 64) {
|
||||
buffer[bufferPos++] = 0;
|
||||
}
|
||||
// process data block:
|
||||
processBuffer();
|
||||
// reset buffer:
|
||||
bufferPos = 0;
|
||||
}
|
||||
while (bufferPos < 32) {
|
||||
buffer[bufferPos++] = 0;
|
||||
}
|
||||
// append bit length of hashed data:
|
||||
System.arraycopy(bitLength, 0, buffer, 32, 32);
|
||||
// process data block:
|
||||
processBuffer();
|
||||
// return the completed message digest:
|
||||
for (int i = 0, j = 0; i < 8; i++, j += 8) {
|
||||
long h = hash[i];
|
||||
digest[j] = (byte) (h >>> 56);
|
||||
digest[j + 1] = (byte) (h >>> 48);
|
||||
digest[j + 2] = (byte) (h >>> 40);
|
||||
digest[j + 3] = (byte) (h >>> 32);
|
||||
digest[j + 4] = (byte) (h >>> 24);
|
||||
digest[j + 5] = (byte) (h >>> 16);
|
||||
digest[j + 6] = (byte) (h >>> 8);
|
||||
digest[j + 7] = (byte) (h);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers string input data to the hashing algorithm.
|
||||
*
|
||||
* @param source plaintext data to hash (ASCII text string).
|
||||
* This method maintains the invariant: bufferBits < 512
|
||||
*/
|
||||
public void NESSIEadd(String source) {
|
||||
if (source.length() > 0) {
|
||||
byte[] data = new byte[source.length()];
|
||||
for (int i = 0; i < source.length(); i++) {
|
||||
data[i] = (byte) source.charAt(i);
|
||||
}
|
||||
NESSIEadd(data, 8 * data.length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password) {
|
||||
byte[] digest = new byte[DIGESTBYTES];
|
||||
NESSIEinit();
|
||||
NESSIEadd(password);
|
||||
NESSIEfinalize(digest);
|
||||
return display(digest);
|
||||
}
|
||||
|
||||
}
|
|
@ -8,6 +8,7 @@ import fr.xephi.authme.security.crypts.description.SaltType;
|
|||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
|
@ -73,9 +74,6 @@ public class Wordpress extends UnsaltedMethod {
|
|||
}
|
||||
int count = 1 << countLog2;
|
||||
String salt = setting.substring(4, 4 + 8);
|
||||
if (salt.length() != 8) {
|
||||
return output;
|
||||
}
|
||||
MessageDigest md = HashUtils.getDigest(MessageDigestAlgorithm.MD5);
|
||||
byte[] pass = stringToUtf8(password);
|
||||
byte[] hash = md.digest(stringToUtf8(salt + password));
|
||||
|
@ -99,16 +97,12 @@ public class Wordpress extends UnsaltedMethod {
|
|||
}
|
||||
|
||||
private byte[] stringToUtf8(String string) {
|
||||
try {
|
||||
return string.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UnsupportedOperationException("This system doesn't support UTF-8!", e);
|
||||
}
|
||||
return string.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password) {
|
||||
byte random[] = new byte[6];
|
||||
byte[] random = new byte[6];
|
||||
randomGen.nextBytes(random);
|
||||
return crypt(password, gensaltPrivate(stringToUtf8(new String(random))));
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import static fr.xephi.authme.security.HashUtils.isEqual;
|
||||
|
||||
@Recommendation(Usage.RECOMMENDED)
|
||||
public class XAuth extends HexSaltedMethod {
|
||||
|
||||
private static String getWhirlpool(String message) {
|
||||
Whirlpool w = new Whirlpool();
|
||||
byte[] digest = new byte[Whirlpool.DIGESTBYTES];
|
||||
w.NESSIEinit();
|
||||
w.NESSIEadd(message);
|
||||
w.NESSIEfinalize(digest);
|
||||
return Whirlpool.display(digest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String computeHash(String password, String salt, String name) {
|
||||
String hash = getWhirlpool(salt + password).toLowerCase();
|
||||
int saltPos = password.length() >= hash.length() ? hash.length() - 1 : password.length();
|
||||
return hash.substring(0, saltPos) + salt + hash.substring(saltPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean comparePassword(String password, HashedPassword hashedPassword, String name) {
|
||||
String hash = hashedPassword.getHash();
|
||||
int saltPos = password.length() >= hash.length() ? hash.length() - 1 : password.length();
|
||||
if (saltPos + 12 > hash.length()) {
|
||||
return false;
|
||||
}
|
||||
String salt = hash.substring(saltPos, saltPos + 12);
|
||||
return isEqual(hash, computeHash(password, salt, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSaltLength() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
}
|
|
@ -55,7 +55,12 @@ public class TotpAuthenticator implements HasCleanup {
|
|||
*/
|
||||
public boolean checkCode(String playerName, String totpKey, String inputCode) {
|
||||
String nameLower = playerName.toLowerCase();
|
||||
Integer totpCode = Ints.tryParse(inputCode);
|
||||
Integer totpCode;
|
||||
try {
|
||||
totpCode = Integer.parseInt(inputCode);
|
||||
} catch (NumberFormatException e) {
|
||||
totpCode = null;
|
||||
}
|
||||
if (totpCode != null && !usedCodes.contains(nameLower, totpCode)
|
||||
&& authenticator.authorize(totpKey, totpCode)) {
|
||||
usedCodes.put(nameLower, totpCode, System.currentTimeMillis());
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.yaml.snakeyaml.Yaml;
|
|||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -54,7 +55,7 @@ public class HelpTranslationGenerator {
|
|||
Map<String, Object> helpEntries = generateHelpMessageEntries();
|
||||
|
||||
String helpEntriesYaml = exportToYaml(helpEntries);
|
||||
Files.write(helpFile.toPath(), helpEntriesYaml.getBytes(), StandardOpenOption.TRUNCATE_EXISTING);
|
||||
Files.write(helpFile.toPath(), helpEntriesYaml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING);
|
||||
return helpFile;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ public final class MigrationService {
|
|||
* @param dataSource The data source
|
||||
* @param authmeSha256 Instance to the AuthMe Sha256 encryption method implementation
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void changePlainTextToSha256(Settings settings, DataSource dataSource,
|
||||
Sha256 authmeSha256) {
|
||||
if (HashAlgorithm.PLAINTEXT == settings.getProperty(SecuritySettings.PASSWORD_HASH)) {
|
||||
|
|
|
@ -131,7 +131,7 @@ public class TeleportationService implements Reloadable {
|
|||
}
|
||||
|
||||
// #856: If LimboPlayer comes from a persisted file, the Location might be null
|
||||
String worldName = (limbo != null && limbo.getLocation() != null)
|
||||
String worldName = (limbo != null && limbo.getLocation() != null && limbo.getLocation().getWorld() != null)
|
||||
? limbo.getLocation().getWorld().getName()
|
||||
: null;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import javax.annotation.PostConstruct;
|
|||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -155,7 +156,7 @@ public class ValidationService implements Reloadable {
|
|||
}
|
||||
|
||||
String ip = PlayerUtils.getPlayerIp(player);
|
||||
String domain = player.getAddress().getHostName();
|
||||
String domain = Objects.requireNonNull(player.getAddress()).getHostName();
|
||||
for (String restriction : restrictions) {
|
||||
if (restriction.startsWith("regex:")) {
|
||||
restriction = restriction.replace("regex:", "");
|
||||
|
|
|
@ -14,6 +14,7 @@ import fr.xephi.authme.settings.properties.HooksSettings;
|
|||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.messaging.Messenger;
|
||||
import org.bukkit.plugin.messaging.PluginMessageListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Optional;
|
||||
|
@ -40,7 +41,7 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
|
|||
}
|
||||
|
||||
@Override
|
||||
public void reload(final Settings settings) {
|
||||
public void reload(Settings settings) {
|
||||
this.isEnabled = settings.getProperty(HooksSettings.BUNGEECORD);
|
||||
|
||||
if (this.isEnabled) {
|
||||
|
@ -56,7 +57,7 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
|
|||
*
|
||||
* @param in the input to handle
|
||||
*/
|
||||
private void handleBroadcast(final ByteArrayDataInput in) {
|
||||
private void handleBroadcast(ByteArrayDataInput in) {
|
||||
// Read data byte array
|
||||
final short dataLength = in.readShort();
|
||||
final byte[] dataBytes = new byte[dataLength];
|
||||
|
@ -130,7 +131,7 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPluginMessageReceived(final String channel, final Player player, final byte[] data) {
|
||||
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte[] data) {
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
@ -146,7 +147,7 @@ public class BungeeReceiver implements PluginMessageListener, SettingsDependent
|
|||
}
|
||||
}
|
||||
|
||||
private void performLogin(final String name) {
|
||||
private void performLogin(String name) {
|
||||
Player player = bukkitService.getPlayerExact(name);
|
||||
if (player != null && player.isOnline()) {
|
||||
management.forceLogin(player);
|
||||
|
|
|
@ -4,13 +4,13 @@ import ch.jalu.configme.SettingsManagerImpl;
|
|||
import ch.jalu.configme.configurationdata.ConfigurationData;
|
||||
import ch.jalu.configme.migration.MigrationService;
|
||||
import ch.jalu.configme.resource.PropertyResource;
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import static fr.xephi.authme.util.FileUtils.copyFileFromResource;
|
||||
|
||||
|
@ -89,7 +89,7 @@ public class Settings extends SettingsManagerImpl {
|
|||
final File file = new File(pluginFolder, filename);
|
||||
if (copyFileFromResource(file, filename)) {
|
||||
try {
|
||||
return Files.asCharSource(file, StandardCharsets.UTF_8).read();
|
||||
return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
logger.logException("Failed to read file '" + filename + "':", e);
|
||||
}
|
||||
|
@ -98,4 +98,5 @@ public class Settings extends SettingsManagerImpl {
|
|||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -309,6 +309,7 @@ public class SettingsMigrationService extends PlainMigrationService {
|
|||
* @param configData Configuration data
|
||||
* @return True if the configuration has changed, false otherwise
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static boolean moveDeprecatedHashAlgorithmIntoLegacySection(PropertyReader reader,
|
||||
ConfigurationData configData) {
|
||||
HashAlgorithm currentHash = SecuritySettings.PASSWORD_HASH.determineValue(reader);
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.bukkit.entity.Player;
|
|||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Manager for spawn points. It loads spawn definitions from AuthMe and third-party plugins
|
||||
|
@ -170,8 +171,10 @@ public class SpawnLoader implements Reloadable {
|
|||
* @see RestrictionSettings#SPAWN_PRIORITY
|
||||
*/
|
||||
public Location getSpawnLocation(Player player) {
|
||||
if (player == null || player.getWorld() == null) {
|
||||
if (player == null) {
|
||||
return null;
|
||||
} else {
|
||||
player.getWorld();
|
||||
}
|
||||
|
||||
World world = player.getWorld();
|
||||
|
@ -179,19 +182,18 @@ public class SpawnLoader implements Reloadable {
|
|||
for (String priority : spawnPriority) {
|
||||
switch (priority.toLowerCase().trim()) {
|
||||
case "default":
|
||||
if (world.getSpawnLocation() != null) {
|
||||
if (!isValidSpawnPoint(world.getSpawnLocation())) {
|
||||
for (World spawnWorld : Bukkit.getWorlds()) {
|
||||
if (isValidSpawnPoint(spawnWorld.getSpawnLocation())) {
|
||||
world = spawnWorld;
|
||||
break;
|
||||
}
|
||||
world.getSpawnLocation();
|
||||
if (!isValidSpawnPoint(world.getSpawnLocation())) {
|
||||
for (World spawnWorld : Bukkit.getWorlds()) {
|
||||
if (isValidSpawnPoint(spawnWorld.getSpawnLocation())) {
|
||||
world = spawnWorld;
|
||||
break;
|
||||
}
|
||||
logger.warning("Seems like AuthMe is unable to find a proper spawn location. "
|
||||
+ "Set a location with the command '/authme setspawn'");
|
||||
}
|
||||
spawnLoc = world.getSpawnLocation();
|
||||
logger.warning("Seems like AuthMe is unable to find a proper spawn location. "
|
||||
+ "Set a location with the command '/authme setspawn'");
|
||||
}
|
||||
spawnLoc = world.getSpawnLocation();
|
||||
break;
|
||||
case "multiverse":
|
||||
if (settings.getProperty(HooksSettings.MULTIVERSE)) {
|
||||
|
@ -228,10 +230,7 @@ public class SpawnLoader implements Reloadable {
|
|||
* @return True upon success, false otherwise
|
||||
*/
|
||||
private boolean isValidSpawnPoint(Location location) {
|
||||
if (location.getX() == 0 && location.getY() == 0 && location.getZ() == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return location.getX() != 0 || location.getY() != 0 || location.getZ() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -290,7 +289,7 @@ public class SpawnLoader implements Reloadable {
|
|||
private static Location getLocationFromConfiguration(FileConfiguration configuration, String pathPrefix) {
|
||||
if (containsAllSpawnFields(configuration, pathPrefix)) {
|
||||
String prefix = pathPrefix + ".";
|
||||
String worldName = configuration.getString(prefix + "world");
|
||||
String worldName = Objects.requireNonNull(configuration.getString(prefix + "world"));
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (!StringUtils.isEmpty(worldName) && world != null) {
|
||||
return new Location(world, configuration.getDouble(prefix + "x"),
|
||||
|
@ -312,7 +311,7 @@ public class SpawnLoader implements Reloadable {
|
|||
final String pathPrefix = "Spawn.Main";
|
||||
if (isLocationCompleteInCmiConfig(configuration, pathPrefix)) {
|
||||
String prefix = pathPrefix + ".";
|
||||
String worldName = configuration.getString(prefix + "World");
|
||||
String worldName = Objects.requireNonNull(configuration.getString(prefix + "World"));
|
||||
World world = Bukkit.getWorld(worldName);
|
||||
if (!StringUtils.isEmpty(worldName) && world != null) {
|
||||
return new Location(world, configuration.getDouble(prefix + "X"),
|
||||
|
|
|
@ -17,7 +17,7 @@ public class OnLoginCommand extends Command {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this object, using the given command as new {@link Command#command command}.
|
||||
* Creates a copy of this object, using the given command.
|
||||
*
|
||||
* @param command the command text to use in the copy
|
||||
* @return copy of the source with the new command
|
||||
|
|
|
@ -53,7 +53,7 @@ public final class SecuritySettings implements SettingsHolder {
|
|||
|
||||
@Comment({
|
||||
"Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512,",
|
||||
"MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,",
|
||||
"MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, JOOMLA, WBB3, WBB4, MD5VB,",
|
||||
"PBKDF2DJANGO, WORDPRESS, ROYALAUTH, ARGON2, CUSTOM (for developers only). See full list at",
|
||||
"https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md",
|
||||
"If you use ARGON2, check that you have the argon2 c library on your system"
|
||||
|
|
|
@ -5,6 +5,7 @@ package fr.xephi.authme.util;
|
|||
* in the given 'interval'.
|
||||
*/
|
||||
public class AtomicIntervalCounter {
|
||||
|
||||
private final int threshold;
|
||||
private final int interval;
|
||||
private int count;
|
||||
|
@ -50,4 +51,5 @@ public class AtomicIntervalCounter {
|
|||
lastInsert = now;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package fr.xephi.authme.util;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -21,8 +25,9 @@ public final class ExceptionUtils {
|
|||
* @param <T> the desired throwable subtype
|
||||
* @return the first throwable found of the given type, or null if none found
|
||||
*/
|
||||
public static <T extends Throwable> T findThrowableInCause(Class<T> wantedThrowableType, Throwable throwable) {
|
||||
Set<Throwable> visitedObjects = Sets.newIdentityHashSet();
|
||||
public static <T extends Throwable> T findThrowableInCause(@NotNull Class<T> wantedThrowableType,
|
||||
@NotNull Throwable throwable) {
|
||||
Set<Throwable> visitedObjects = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||
Throwable currentThrowable = throwable;
|
||||
while (currentThrowable != null && !visitedObjects.contains(currentThrowable)) {
|
||||
if (wantedThrowableType.isInstance(currentThrowable)) {
|
||||
|
@ -40,7 +45,22 @@ public final class ExceptionUtils {
|
|||
* @param th the throwable to process
|
||||
* @return string with the type of the Throwable and its message, e.g. "[IOException]: Could not open stream"
|
||||
*/
|
||||
public static String formatException(Throwable th) {
|
||||
@NotNull
|
||||
public static String formatException(@NotNull Throwable th) {
|
||||
return "[" + th.getClass().getSimpleName() + "]: " + th.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string containing the result of {@link Throwable#toString()}, followed by the full, recursive
|
||||
* stack trace of {@code throwable}.
|
||||
*
|
||||
* @param throwable the throwable to precess
|
||||
* @return string containing the stacktrace
|
||||
*/
|
||||
public static String getStackTraceAsString(Throwable throwable) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
throwable.printStackTrace(new PrintWriter(stringWriter));
|
||||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package fr.xephi.authme.util;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
|
@ -21,7 +22,7 @@ public final class FileUtils {
|
|||
private static final DateTimeFormatter CURRENT_DATE_STRING_FORMATTER =
|
||||
DateTimeFormatter.ofPattern("yyyyMMdd_HHmm");
|
||||
|
||||
private static ConsoleLogger logger = ConsoleLoggerFactory.get(FileUtils.class);
|
||||
private static final ConsoleLogger logger = ConsoleLoggerFactory.get(FileUtils.class);
|
||||
|
||||
// Utility class
|
||||
private FileUtils() {
|
||||
|
@ -35,7 +36,7 @@ public final class FileUtils {
|
|||
*
|
||||
* @return False if the file does not exist and could not be copied, true otherwise
|
||||
*/
|
||||
public static boolean copyFileFromResource(File destinationFile, String resourcePath) {
|
||||
public static boolean copyFileFromResource(@NotNull File destinationFile, @NotNull String resourcePath) {
|
||||
if (destinationFile.exists()) {
|
||||
return true;
|
||||
} else if (!createDirectory(destinationFile.getParentFile())) {
|
||||
|
@ -48,7 +49,7 @@ public final class FileUtils {
|
|||
logger.warning(format("Cannot copy resource '%s' to file '%s': cannot load resource",
|
||||
resourcePath, destinationFile.getPath()));
|
||||
} else {
|
||||
java.nio.file.Files.copy(is, destinationFile.toPath());
|
||||
Files.copy(is, destinationFile.toPath());
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@ -64,7 +65,7 @@ public final class FileUtils {
|
|||
* @param dir the directory to create
|
||||
* @return true upon success, false otherwise
|
||||
*/
|
||||
public static boolean createDirectory(File dir) {
|
||||
public static boolean createDirectory(@NotNull File dir) {
|
||||
if (!dir.exists() && !dir.mkdirs()) {
|
||||
logger.warning("Could not create directory '" + dir + "'");
|
||||
return false;
|
||||
|
@ -72,6 +73,34 @@ public final class FileUtils {
|
|||
return dir.isDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the given directory, throws a runtime exception on fail.
|
||||
*
|
||||
* @param dir the directory to create
|
||||
* @throws IllegalStateException when unable to create the directory
|
||||
*/
|
||||
public static void createDirectoryOrFail(@NotNull File dir) {
|
||||
if (!dir.exists() && !dir.mkdirs() || !dir.isDirectory()) {
|
||||
throw new IllegalStateException("Could not create directory '" + dir + "'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the given file, throws a runtime exception on fail.
|
||||
*
|
||||
* @param file the file to create
|
||||
* @throws IllegalStateException when unable to create the file
|
||||
*/
|
||||
public static void createFileOrFail(@NotNull File file) {
|
||||
try {
|
||||
if (!file.exists() && !file.createNewFile() || !file.isFile()) {
|
||||
throw new IllegalStateException("Could not create file '" + file + "'");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Could not create file '" + file + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JAR file as stream. Returns null if it doesn't exist.
|
||||
*
|
||||
|
@ -165,9 +194,10 @@ public final class FileUtils {
|
|||
* @return path to a file suitably named for storing a backup
|
||||
*/
|
||||
public static String createBackupFilePath(File file) {
|
||||
String filename = "backup_" + Files.getNameWithoutExtension(file.getName())
|
||||
String filename = "backup_" + com.google.common.io.Files.getNameWithoutExtension(file.getName())
|
||||
+ "_" + createCurrentTimeString()
|
||||
+ "." + Files.getFileExtension(file.getName());
|
||||
+ "." + com.google.common.io.Files.getFileExtension(file.getName());
|
||||
return makePath(file.getParent(), filename);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
|
@ -18,7 +20,7 @@ public final class InternetProtocolUtils {
|
|||
* @param address address to check
|
||||
* @return true if the address is a local (site and link) or loopback address, false otherwise
|
||||
*/
|
||||
public static boolean isLocalAddress(String address) {
|
||||
public static boolean isLocalAddress(@NotNull String address) {
|
||||
try {
|
||||
InetAddress inetAddress = InetAddress.getByName(address);
|
||||
|
||||
|
@ -48,7 +50,7 @@ public final class InternetProtocolUtils {
|
|||
* @param address address to check
|
||||
* @return true if the address is a loopback one
|
||||
*/
|
||||
public static boolean isLoopbackAddress(String address) {
|
||||
public static boolean isLoopbackAddress(@NotNull String address) {
|
||||
try {
|
||||
InetAddress inetAddress = InetAddress.getByName(address);
|
||||
return inetAddress.isLoopbackAddress();
|
||||
|
@ -57,11 +59,7 @@ public final class InternetProtocolUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isLoopbackAddress(InetAddress address) {
|
||||
return address.isLoopbackAddress();
|
||||
}
|
||||
|
||||
private static boolean isIPv6UniqueSiteLocal(InetAddress address) {
|
||||
private static boolean isIPv6UniqueSiteLocal(@NotNull InetAddress address) {
|
||||
// ref: https://en.wikipedia.org/wiki/Unique_local_address
|
||||
|
||||
// currently undefined but could be used in the near future fc00::/8
|
||||
|
@ -69,4 +67,5 @@ public final class InternetProtocolUtils {
|
|||
// in use for unique site-local fd00::/8
|
||||
|| (address.getAddress()[0] & 0xFF) == 0xFD;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package fr.xephi.authme.util;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Player utilities.
|
||||
|
@ -15,9 +18,12 @@ public final class PlayerUtils {
|
|||
* Returns the IP of the given player.
|
||||
*
|
||||
* @param player The player to return the IP address for
|
||||
*
|
||||
* @return The player's IP address
|
||||
*/
|
||||
public static String getPlayerIp(Player player) {
|
||||
@NotNull
|
||||
public static String getPlayerIp(@NotNull Player player) {
|
||||
Objects.requireNonNull(player.getAddress(), "address");
|
||||
return player.getAddress().getAddress().getHostAddress();
|
||||
}
|
||||
|
||||
|
@ -25,9 +31,10 @@ public final class PlayerUtils {
|
|||
* Returns if the player is an NPC or not.
|
||||
*
|
||||
* @param player The player to check
|
||||
*
|
||||
* @return True if the player is an NPC, false otherwise
|
||||
*/
|
||||
public static boolean isNpc(Player player) {
|
||||
public static boolean isNpc(@NotNull Player player) {
|
||||
return player.hasMetadata("NPC");
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package fr.xephi.authme.util;
|
|||
import net.ricecode.similarity.LevenshteinDistanceStrategy;
|
||||
import net.ricecode.similarity.StringSimilarityService;
|
||||
import net.ricecode.similarity.StringSimilarityServiceImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Utility class for String operations.
|
||||
|
@ -42,7 +43,7 @@ public final class StringUtils {
|
|||
*
|
||||
* @return True if the string contains at least one of the items
|
||||
*/
|
||||
public static boolean containsAny(String str, Iterable<String> pieces) {
|
||||
public static boolean containsAny(String str, @NotNull Iterable<String> pieces) {
|
||||
if (str == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -77,8 +78,9 @@ public final class StringUtils {
|
|||
*/
|
||||
// Note ljacqu 20170314: `needle` is restricted to char type intentionally because something like
|
||||
// isInsideString("11", "2211") would unexpectedly return true...
|
||||
public static boolean isInsideString(char needle, String haystack) {
|
||||
public static boolean isInsideString(char needle, @NotNull String haystack) {
|
||||
int index = haystack.indexOf(needle);
|
||||
return index > 0 && index < haystack.length() - 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import fr.xephi.authme.output.ConsoleLoggerFactory;
|
|||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -17,7 +18,7 @@ public final class Utils {
|
|||
/** Number of milliseconds in a minute. */
|
||||
public static final long MILLIS_PER_MINUTE = 60_000L;
|
||||
|
||||
private static ConsoleLogger logger = ConsoleLoggerFactory.get(Utils.class);
|
||||
private static final ConsoleLogger logger = ConsoleLoggerFactory.get(Utils.class);
|
||||
|
||||
// Utility class
|
||||
private Utils() {
|
||||
|
@ -30,7 +31,8 @@ public final class Utils {
|
|||
*
|
||||
* @return the given regex compiled into Pattern object.
|
||||
*/
|
||||
public static Pattern safePatternCompile(String pattern) {
|
||||
@NotNull
|
||||
public static Pattern safePatternCompile(@NotNull String pattern) {
|
||||
try {
|
||||
return Pattern.compile(pattern);
|
||||
} catch (Exception e) {
|
||||
|
@ -46,7 +48,7 @@ public final class Utils {
|
|||
*
|
||||
* @return true if the class is loaded, false otherwise
|
||||
*/
|
||||
public static boolean isClassLoaded(String className) {
|
||||
public static boolean isClassLoaded(@NotNull String className) {
|
||||
try {
|
||||
Class.forName(className);
|
||||
return true;
|
||||
|
@ -63,7 +65,7 @@ public final class Utils {
|
|||
* @param sender the sender to inform
|
||||
* @param message the message to log and send
|
||||
*/
|
||||
public static void logAndSendMessage(CommandSender sender, String message) {
|
||||
public static void logAndSendMessage(CommandSender sender, @NotNull String message) {
|
||||
logger.info(message);
|
||||
// Make sure sender is not console user, which will see the message from ConsoleLogger already
|
||||
if (sender != null && !(sender instanceof ConsoleCommandSender)) {
|
||||
|
@ -79,7 +81,7 @@ public final class Utils {
|
|||
* @param sender the sender to inform
|
||||
* @param message the warning to log and send
|
||||
*/
|
||||
public static void logAndSendWarning(CommandSender sender, String message) {
|
||||
public static void logAndSendWarning(CommandSender sender, @NotNull String message) {
|
||||
logger.warning(message);
|
||||
// Make sure sender is not console user, which will see the message from ConsoleLogger already
|
||||
if (sender != null && !(sender instanceof ConsoleCommandSender)) {
|
||||
|
@ -107,4 +109,5 @@ public final class Utils {
|
|||
public static boolean isEmailEmpty(String email) {
|
||||
return StringUtils.isEmpty(email) || "your@email.com".equalsIgnoreCase(email);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,4 +24,5 @@ public final class UuidUtils {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.expiring;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -8,6 +10,7 @@ import java.util.concurrent.TimeUnit;
|
|||
public class Duration {
|
||||
|
||||
private final long duration;
|
||||
@NotNull
|
||||
private final TimeUnit unit;
|
||||
|
||||
/**
|
||||
|
@ -16,7 +19,7 @@ public class Duration {
|
|||
* @param duration the duration
|
||||
* @param unit the time unit in which {@code duration} is expressed
|
||||
*/
|
||||
public Duration(long duration, TimeUnit unit) {
|
||||
public Duration(long duration, @NotNull TimeUnit unit) {
|
||||
this.duration = duration;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
@ -38,7 +41,8 @@ public class Duration {
|
|||
* @param sourceUnit the time unit the duration is expressed in
|
||||
* @return Duration object using the most suitable time unit
|
||||
*/
|
||||
public static Duration createWithSuitableUnit(long sourceDuration, TimeUnit sourceUnit) {
|
||||
@NotNull
|
||||
public static Duration createWithSuitableUnit(long sourceDuration, @NotNull TimeUnit sourceUnit) {
|
||||
long durationMillis = Math.abs(TimeUnit.MILLISECONDS.convert(sourceDuration, sourceUnit));
|
||||
|
||||
TimeUnit targetUnit;
|
||||
|
@ -66,7 +70,9 @@ public class Duration {
|
|||
/**
|
||||
* @return the time unit in which the duration is expressed
|
||||
*/
|
||||
@NotNull
|
||||
public TimeUnit getTimeUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.expiring;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -24,6 +26,7 @@ import java.util.concurrent.TimeUnit;
|
|||
*/
|
||||
public class ExpiringMap<K, V> {
|
||||
|
||||
@NotNull
|
||||
private final Map<K, ExpiringEntry<V>> entries = new ConcurrentHashMap<>();
|
||||
private long expirationMillis;
|
||||
|
||||
|
@ -33,7 +36,7 @@ public class ExpiringMap<K, V> {
|
|||
* @param duration the duration of time after which entries expire
|
||||
* @param unit the time unit in which {@code duration} is expressed
|
||||
*/
|
||||
public ExpiringMap(long duration, TimeUnit unit) {
|
||||
public ExpiringMap(long duration, @NotNull TimeUnit unit) {
|
||||
setExpiration(duration, unit);
|
||||
}
|
||||
|
||||
|
@ -44,7 +47,7 @@ public class ExpiringMap<K, V> {
|
|||
* @param key the key to look up
|
||||
* @return the associated value, or {@code null} if not available
|
||||
*/
|
||||
public V get(K key) {
|
||||
public V get(@NotNull K key) {
|
||||
ExpiringEntry<V> value = entries.get(key);
|
||||
if (value == null) {
|
||||
return null;
|
||||
|
@ -62,7 +65,7 @@ public class ExpiringMap<K, V> {
|
|||
* @param key the key to insert a value for
|
||||
* @param value the value to insert
|
||||
*/
|
||||
public void put(K key, V value) {
|
||||
public void put(@NotNull K key, @NotNull V value) {
|
||||
long expiration = System.currentTimeMillis() + expirationMillis;
|
||||
entries.put(key, new ExpiringEntry<>(value, expiration));
|
||||
}
|
||||
|
@ -72,7 +75,7 @@ public class ExpiringMap<K, V> {
|
|||
*
|
||||
* @param key the key to remove the value for
|
||||
*/
|
||||
public void remove(K key) {
|
||||
public void remove(@NotNull K key) {
|
||||
entries.remove(key);
|
||||
}
|
||||
|
||||
|
@ -90,7 +93,7 @@ public class ExpiringMap<K, V> {
|
|||
* @param duration the duration of time after which entries expire
|
||||
* @param unit the time unit in which {@code duration} is expressed
|
||||
*/
|
||||
public void setExpiration(long duration, TimeUnit unit) {
|
||||
public void setExpiration(long duration, @NotNull TimeUnit unit) {
|
||||
this.expirationMillis = unit.toMillis(duration);
|
||||
}
|
||||
|
||||
|
@ -108,6 +111,7 @@ public class ExpiringMap<K, V> {
|
|||
/**
|
||||
* @return the internal map
|
||||
*/
|
||||
@NotNull
|
||||
protected Map<K, ExpiringEntry<V>> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
@ -119,15 +123,16 @@ public class ExpiringMap<K, V> {
|
|||
*/
|
||||
protected static final class ExpiringEntry<V> {
|
||||
|
||||
@NotNull
|
||||
private final V value;
|
||||
private final long expiration;
|
||||
|
||||
ExpiringEntry(V value, long expiration) {
|
||||
ExpiringEntry(@NotNull V value, long expiration) {
|
||||
this.value = value;
|
||||
this.expiration = expiration;
|
||||
}
|
||||
|
||||
V getValue() {
|
||||
@NotNull V getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -135,4 +140,5 @@ public class ExpiringMap<K, V> {
|
|||
return expiration;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.expiring;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -18,7 +20,8 @@ import java.util.concurrent.TimeUnit;
|
|||
*/
|
||||
public class ExpiringSet<E> {
|
||||
|
||||
private Map<E, Long> entries = new ConcurrentHashMap<>();
|
||||
@NotNull
|
||||
private final Map<E, Long> entries = new ConcurrentHashMap<>();
|
||||
private long expirationMillis;
|
||||
|
||||
/**
|
||||
|
@ -27,7 +30,7 @@ public class ExpiringSet<E> {
|
|||
* @param duration the duration of time after which entries expire
|
||||
* @param unit the time unit in which {@code duration} is expressed
|
||||
*/
|
||||
public ExpiringSet(long duration, TimeUnit unit) {
|
||||
public ExpiringSet(long duration, @NotNull TimeUnit unit) {
|
||||
setExpiration(duration, unit);
|
||||
}
|
||||
|
||||
|
@ -36,7 +39,7 @@ public class ExpiringSet<E> {
|
|||
*
|
||||
* @param entry the entry to add
|
||||
*/
|
||||
public void add(E entry) {
|
||||
public void add(@NotNull E entry) {
|
||||
entries.put(entry, System.currentTimeMillis() + expirationMillis);
|
||||
}
|
||||
|
||||
|
@ -46,7 +49,7 @@ public class ExpiringSet<E> {
|
|||
* @param entry the entry to check
|
||||
* @return true if the entry is present and not expired, false otherwise
|
||||
*/
|
||||
public boolean contains(E entry) {
|
||||
public boolean contains(@NotNull E entry) {
|
||||
Long expiration = entries.get(entry);
|
||||
if (expiration == null) {
|
||||
return false;
|
||||
|
@ -63,7 +66,7 @@ public class ExpiringSet<E> {
|
|||
*
|
||||
* @param entry the entry to remove
|
||||
*/
|
||||
public void remove(E entry) {
|
||||
public void remove(@NotNull E entry) {
|
||||
entries.remove(entry);
|
||||
}
|
||||
|
||||
|
@ -88,7 +91,8 @@ public class ExpiringSet<E> {
|
|||
* @param entry the entry whose duration before it expires should be returned
|
||||
* @return duration the entry will remain in the set (if there are not modifications)
|
||||
*/
|
||||
public Duration getExpiration(E entry) {
|
||||
@NotNull
|
||||
public Duration getExpiration(@NotNull E entry) {
|
||||
Long expiration = entries.get(entry);
|
||||
if (expiration == null) {
|
||||
return new Duration(-1, TimeUnit.SECONDS);
|
||||
|
@ -108,7 +112,7 @@ public class ExpiringSet<E> {
|
|||
* @param duration the duration of time after which entries expire
|
||||
* @param unit the time unit in which {@code duration} is expressed
|
||||
*/
|
||||
public void setExpiration(long duration, TimeUnit unit) {
|
||||
public void setExpiration(long duration, @NotNull TimeUnit unit) {
|
||||
this.expirationMillis = unit.toMillis(duration);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.expiring;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -18,12 +20,13 @@ public class TimedCounter<K> extends ExpiringMap<K, Integer> {
|
|||
* @param duration the duration of time after which entries expire
|
||||
* @param unit the time unit in which {@code duration} is expressed
|
||||
*/
|
||||
public TimedCounter(long duration, TimeUnit unit) {
|
||||
public TimedCounter(long duration, @NotNull TimeUnit unit) {
|
||||
super(duration, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get(K key) {
|
||||
@NotNull
|
||||
public Integer get(@NotNull K key) {
|
||||
Integer value = super.get(key);
|
||||
return value == null ? 0 : value;
|
||||
}
|
||||
|
@ -33,7 +36,7 @@ public class TimedCounter<K> extends ExpiringMap<K, Integer> {
|
|||
*
|
||||
* @param key the key to increment the counter for
|
||||
*/
|
||||
public void increment(K key) {
|
||||
public void increment(@NotNull K key) {
|
||||
put(key, get(key) + 1);
|
||||
}
|
||||
|
||||
|
@ -43,7 +46,7 @@ public class TimedCounter<K> extends ExpiringMap<K, Integer> {
|
|||
*
|
||||
* @param key the key to increment the counter for
|
||||
*/
|
||||
public void decrement(K key) {
|
||||
public void decrement(@NotNull K key) {
|
||||
ExpiringEntry<Integer> e = getEntries().get(key);
|
||||
|
||||
if (e != null) {
|
||||
|
@ -67,4 +70,5 @@ public class TimedCounter<K> extends ExpiringMap<K, Integer> {
|
|||
.map(ExpiringEntry::getValue)
|
||||
.reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
|
@ -9,7 +11,9 @@ import java.util.function.Function;
|
|||
*/
|
||||
public class DependentTag<A> implements Tag<A> {
|
||||
|
||||
@NotNull
|
||||
private final String name;
|
||||
@NotNull
|
||||
private final Function<A, String> replacementFunction;
|
||||
|
||||
/**
|
||||
|
@ -18,18 +22,21 @@ public class DependentTag<A> implements Tag<A> {
|
|||
* @param name the tag (placeholder) that will be replaced
|
||||
* @param replacementFunction the function producing the replacement
|
||||
*/
|
||||
public DependentTag(String name, Function<A, String> replacementFunction) {
|
||||
public DependentTag(@NotNull String name,@NotNull Function<A, String> replacementFunction) {
|
||||
this.name = name;
|
||||
this.replacementFunction = replacementFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(A argument) {
|
||||
@NotNull
|
||||
public String getValue(@NotNull A argument) {
|
||||
return replacementFunction.apply(argument);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
|
@ -9,21 +11,26 @@ import java.util.function.Supplier;
|
|||
*/
|
||||
public class SimpleTag<A> implements Tag<A> {
|
||||
|
||||
@NotNull
|
||||
private final String name;
|
||||
@NotNull
|
||||
private final Supplier<String> replacementFunction;
|
||||
|
||||
public SimpleTag(String name, Supplier<String> replacementFunction) {
|
||||
public SimpleTag(@NotNull String name, @NotNull Supplier<String> replacementFunction) {
|
||||
this.name = name;
|
||||
this.replacementFunction = replacementFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getValue(A argument) {
|
||||
return replacementFunction.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a tag in a text to be replaced with a value (which may depend on some argument).
|
||||
*
|
||||
|
@ -10,6 +12,7 @@ public interface Tag<A> {
|
|||
/**
|
||||
* @return the tag to replace
|
||||
*/
|
||||
@NotNull
|
||||
String getName();
|
||||
|
||||
/**
|
||||
|
@ -18,5 +21,7 @@ public interface Tag<A> {
|
|||
* @param argument the argument to evaluate the replacement for
|
||||
* @return the replacement
|
||||
*/
|
||||
@NotNull
|
||||
String getValue(A argument);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
@ -11,11 +13,14 @@ public final class TagBuilder {
|
|||
private TagBuilder() {
|
||||
}
|
||||
|
||||
public static <A> Tag<A> createTag(String name, Function<A, String> replacementFunction) {
|
||||
@NotNull
|
||||
public static <A> Tag<A> createTag(@NotNull String name, @NotNull Function<A, String> replacementFunction) {
|
||||
return new DependentTag<>(name, replacementFunction);
|
||||
}
|
||||
|
||||
public static <A> Tag<A> createTag(String name, Supplier<String> replacementFunction) {
|
||||
@NotNull
|
||||
public static <A> Tag<A> createTag(@NotNull String name, @NotNull Supplier<String> replacementFunction) {
|
||||
return new SimpleTag<>(name, replacementFunction);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -13,7 +15,9 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public final class TagReplacer<A> {
|
||||
|
||||
@NotNull
|
||||
private final List<Tag<A>> tags;
|
||||
@NotNull
|
||||
private final Collection<String> messages;
|
||||
|
||||
/**
|
||||
|
@ -22,7 +26,7 @@ public final class TagReplacer<A> {
|
|||
* @param tags the tags that are being used in the messages
|
||||
* @param messages the messages
|
||||
*/
|
||||
private TagReplacer(List<Tag<A>> tags, Collection<String> messages) {
|
||||
private TagReplacer(@NotNull List<Tag<A>> tags, @NotNull Collection<String> messages) {
|
||||
this.tags = tags;
|
||||
this.messages = messages;
|
||||
}
|
||||
|
@ -36,7 +40,9 @@ public final class TagReplacer<A> {
|
|||
* @param <A> the argument type
|
||||
* @return new tag replacer instance
|
||||
*/
|
||||
public static <A> TagReplacer<A> newReplacer(Collection<Tag<A>> allTags, Collection<String> messages) {
|
||||
@NotNull
|
||||
public static <A> TagReplacer<A> newReplacer(@NotNull Collection<Tag<A>> allTags,
|
||||
@NotNull Collection<String> messages) {
|
||||
List<Tag<A>> usedTags = determineUsedTags(allTags, messages);
|
||||
return new TagReplacer<>(usedTags, messages);
|
||||
}
|
||||
|
@ -47,7 +53,8 @@ public final class TagReplacer<A> {
|
|||
* @param argument the argument to get the messages for
|
||||
* @return the adapted messages
|
||||
*/
|
||||
public List<String> getAdaptedMessages(A argument) {
|
||||
@NotNull
|
||||
public List<String> getAdaptedMessages(@NotNull A argument) {
|
||||
// Note ljacqu 20170121: Using a Map might seem more natural here but we avoid doing so for performance
|
||||
// Although the performance gain here is probably minimal...
|
||||
List<TagValue> tagValues = new LinkedList<>();
|
||||
|
@ -74,7 +81,9 @@ public final class TagReplacer<A> {
|
|||
* @param <A> argument type
|
||||
* @return tags used at least once
|
||||
*/
|
||||
private static <A> List<Tag<A>> determineUsedTags(Collection<Tag<A>> allTags, Collection<String> messages) {
|
||||
@NotNull
|
||||
private static <A> List<Tag<A>> determineUsedTags(@NotNull Collection<Tag<A>> allTags,
|
||||
@NotNull Collection<String> messages) {
|
||||
return allTags.stream()
|
||||
.filter(tag -> messages.stream().anyMatch(msg -> msg.contains(tag.getName())))
|
||||
.collect(Collectors.toList());
|
||||
|
@ -84,11 +93,13 @@ public final class TagReplacer<A> {
|
|||
private static final class TagValue {
|
||||
|
||||
/** The tag to replace. */
|
||||
@NotNull
|
||||
private final String tag;
|
||||
/** The value to replace with. */
|
||||
@NotNull
|
||||
private final String value;
|
||||
|
||||
TagValue(String tag, String value) {
|
||||
TagValue(@NotNull String tag, @NotNull String value) {
|
||||
this.tag = tag;
|
||||
this.value = value;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
@ -18,8 +20,11 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public class WrappedTagReplacer<T, A> {
|
||||
|
||||
@NotNull
|
||||
private final Collection<T> items;
|
||||
@NotNull
|
||||
private final BiFunction<T, String, ? extends T> itemCreator;
|
||||
@NotNull
|
||||
private final TagReplacer<A> tagReplacer;
|
||||
|
||||
/**
|
||||
|
@ -30,10 +35,10 @@ public class WrappedTagReplacer<T, A> {
|
|||
* @param stringGetter getter of the String property to adapt on the items
|
||||
* @param itemCreator a function taking (T, String): the original item and the adapted String, returning a new item
|
||||
*/
|
||||
public WrappedTagReplacer(Collection<Tag<A>> allTags,
|
||||
Collection<T> items,
|
||||
Function<? super T, String> stringGetter,
|
||||
BiFunction<T, String, ? extends T> itemCreator) {
|
||||
public WrappedTagReplacer(@NotNull Collection<Tag<A>> allTags,
|
||||
@NotNull Collection<T> items,
|
||||
@NotNull Function<? super T, String> stringGetter,
|
||||
@NotNull BiFunction<T, String, ? extends T> itemCreator) {
|
||||
this.items = items;
|
||||
this.itemCreator = itemCreator;
|
||||
|
||||
|
@ -47,7 +52,8 @@ public class WrappedTagReplacer<T, A> {
|
|||
* @param argument the argument to adapt the items for
|
||||
* @return the adapted items
|
||||
*/
|
||||
public List<T> getAdaptedItems(A argument) {
|
||||
@NotNull
|
||||
public List<T> getAdaptedItems(@NotNull A argument) {
|
||||
List<String> adaptedStrings = tagReplacer.getAdaptedMessages(argument);
|
||||
List<T> adaptedItems = new LinkedList<>();
|
||||
|
||||
|
@ -58,4 +64,5 @@ public class WrappedTagReplacer<T, A> {
|
|||
}
|
||||
return adaptedItems;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<!--suppress HtmlUnknownTag, CheckEmptyScriptTag -->
|
||||
<h1>
|
||||
Dear <playername />,
|
||||
</h1>
|
||||
|
@ -15,4 +16,4 @@ Do not forget to change password after login!<br />
|
|||
</p>
|
||||
<p>
|
||||
See you on <servername />!
|
||||
</p>
|
||||
</p>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<!--suppress HtmlUnknownTag, CheckEmptyScriptTag -->
|
||||
<h1>Dear <playername />,</h1>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<!--suppress HtmlUnknownTag, CheckEmptyScriptTag -->
|
||||
<h1>
|
||||
Dear <playername />,
|
||||
</h1>
|
||||
|
|
|
@ -4,7 +4,6 @@ import ch.jalu.configme.resource.PropertyReader;
|
|||
import ch.jalu.configme.resource.PropertyResource;
|
||||
import ch.jalu.injector.Injector;
|
||||
import ch.jalu.injector.InjectorBuilder;
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||
import fr.xephi.authme.command.CommandHandler;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
|
@ -35,6 +34,8 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Collections;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
@ -72,7 +73,8 @@ public class AuthMeInitializationTest {
|
|||
dataFolder = temporaryFolder.newFolder();
|
||||
File settingsFile = new File(dataFolder, "config.yml");
|
||||
JavaPluginLoader pluginLoader = new JavaPluginLoader(server);
|
||||
Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "config.test.yml"), settingsFile);
|
||||
Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "config.test.yml").toPath(),
|
||||
settingsFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
// Mock / wire various Bukkit components
|
||||
given(server.getLogger()).willReturn(Logger.getAnonymousLogger());
|
||||
|
|
|
@ -12,7 +12,6 @@ import fr.xephi.authme.datasource.columnshandler.PlayerAuthColumn;
|
|||
import fr.xephi.authme.datasource.mysqlextensions.MySqlExtension;
|
||||
import fr.xephi.authme.initialization.HasCleanup;
|
||||
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
||||
import fr.xephi.authme.security.crypts.Whirlpool;
|
||||
import fr.xephi.authme.util.expiring.ExpiringMap;
|
||||
import fr.xephi.authme.util.expiring.ExpiringSet;
|
||||
import fr.xephi.authme.util.expiring.TimedCounter;
|
||||
|
@ -61,7 +60,6 @@ public class ClassesConsistencyTest {
|
|||
|
||||
/** Classes excluded from the field visibility test. */
|
||||
private static final Set<Class<?>> CLASSES_EXCLUDED_FROM_VISIBILITY_TEST = ImmutableSet.of(
|
||||
Whirlpool.class, // not our implementation, so we don't touch it
|
||||
MySqlExtension.class, // has immutable protected fields used by all children
|
||||
AbstractSqlDataSource.class, // protected members for inheritance
|
||||
Columns.class // uses non-static String constants, which is safe
|
||||
|
|
|
@ -61,7 +61,6 @@ public final class ReflectionTestUtils {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T, V> V getFieldValue(Class<T> clazz, T instance, String fieldName) {
|
||||
Field field = getField(clazz, fieldName);
|
||||
return getFieldValue(field, instance);
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static fr.xephi.authme.TestHelper.getJarFile;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
|
@ -68,6 +69,7 @@ public class CommandConsistencyTest {
|
|||
private static Map<String, List<String>> getLabelsFromPluginFile() {
|
||||
FileConfiguration pluginFile = YamlConfiguration.loadConfiguration(getJarFile("/plugin.yml"));
|
||||
MemorySection commandList = (MemorySection) pluginFile.get("commands");
|
||||
Objects.requireNonNull(commandList);
|
||||
Map<String, Object> commandDefinitions = commandList.getValues(false);
|
||||
|
||||
Map<String, List<String>> commandLabels = new HashMap<>();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package fr.xephi.authme.command.executable.authme.debug;
|
||||
|
||||
import ch.jalu.injector.factory.SingletonStore;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import fr.xephi.authme.ReflectionTestUtils;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
|
@ -40,6 +39,7 @@ import static org.mockito.Mockito.verify;
|
|||
/**
|
||||
* Test for {@link DataStatistics}.
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DataStatisticsTest {
|
||||
|
||||
|
@ -99,9 +99,9 @@ public class DataStatisticsTest {
|
|||
public void shouldOutputCachedDataSourceStatistics() {
|
||||
// given
|
||||
CacheDataSource cacheDataSource = mock(CacheDataSource.class);
|
||||
LoadingCache<String, Optional<PlayerAuth>> cache = mock(LoadingCache.class);
|
||||
given(cache.size()).willReturn(11L);
|
||||
given(cacheDataSource.getCachedAuths()).willReturn(cache);
|
||||
Map<String, Optional<PlayerAuth>> cacheValues = mock(Map.class);
|
||||
given(cacheValues.size()).willReturn(11);
|
||||
given(cacheDataSource.getCachedAuths()).willReturn(cacheValues);
|
||||
ReflectionTestUtils.setField(DataStatistics.class, dataStatistics, "dataSource", cacheDataSource);
|
||||
CommandSender sender = mock(CommandSender.class);
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ public class HasPermissionCheckerTest {
|
|||
@Mock
|
||||
private BukkitService bukkitService;
|
||||
|
||||
@SuppressWarnings("FuseStreamOperations")
|
||||
@Test
|
||||
public void shouldListAllPermissionNodeClasses() {
|
||||
// given
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.junit.Test;
|
|||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -55,7 +56,7 @@ public class HelpMessagesConsistencyTest {
|
|||
FileConfiguration configuration = YamlConfiguration.loadConfiguration(DEFAULT_MESSAGES_FILE);
|
||||
|
||||
// when
|
||||
Object commands = configuration.get("commands");
|
||||
Object commands = Objects.requireNonNull(configuration.get("commands"));
|
||||
|
||||
// then
|
||||
assertThat(commands, instanceOf(MemorySection.class));
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package fr.xephi.authme.command.help;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.ReflectionTestUtils;
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.command.CommandDescription;
|
||||
|
@ -11,6 +10,7 @@ import fr.xephi.authme.message.MessagePathHelper;
|
|||
import fr.xephi.authme.permission.DefaultPermission;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
@ -18,6 +18,8 @@ import org.junit.rules.TemporaryFolder;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Collection;
|
||||
|
||||
import static fr.xephi.authme.command.TestCommandsUtil.getCommandWithLabel;
|
||||
|
@ -45,9 +47,10 @@ public class HelpMessagesServiceTest {
|
|||
@Before
|
||||
public void initializeHandler() throws IOException {
|
||||
dataFolder = temporaryFolder.newFolder();
|
||||
new File(dataFolder, "messages").mkdirs();
|
||||
FileUtils.createDirectoryOrFail(new File(dataFolder, "messages"));
|
||||
File messagesFile = new File(dataFolder, MessagePathHelper.createHelpMessageFilePath("test"));
|
||||
Files.copy(TestHelper.getJarFile(TEST_FILE), messagesFile);
|
||||
Files.copy(TestHelper.getJarFile(TEST_FILE).toPath(), messagesFile.toPath(),
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
HelpMessagesFileHandler helpMessagesFileHandler = createMessagesFileHandler();
|
||||
helpMessagesService = new HelpMessagesService(helpMessagesFileHandler);
|
||||
|
|
|
@ -84,7 +84,6 @@ public class RegistrationCaptchaManagerTest {
|
|||
assertThat(captchaManager.checkCode(player, captcha1), equalTo(true));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static ExpiringMap<String, String> getCodeMap(RegistrationCaptchaManager captchaManager) {
|
||||
CaptchaCodeStorage captchaStorage = ReflectionTestUtils.getFieldValue(
|
||||
RegistrationCaptchaManager.class, captchaManager, "captchaCodeStorage");
|
||||
|
|
|
@ -21,7 +21,7 @@ public final class LimboPlayerMatchers {
|
|||
}
|
||||
|
||||
public static Matcher<LimboPlayer> isLimbo(LimboPlayer limbo) {
|
||||
String[] groups = limbo.getGroups().toArray(new String[limbo.getGroups().size()]);
|
||||
String[] groups = limbo.getGroups().toArray(new String[0]);
|
||||
return isLimbo(limbo.isOperator(), limbo.isCanFly(), limbo.getWalkSpeed(), limbo.getFlySpeed(), groups);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public final class LimboPlayerMatchers {
|
|||
@Override
|
||||
protected boolean matchesSafely(LimboPlayer item) {
|
||||
Location location = item.getLocation();
|
||||
return location.getWorld().getName().equals(world)
|
||||
return location.getWorld() != null && location.getWorld().getName().equals(world)
|
||||
&& location.getX() == x && location.getY() == y && location.getZ() == z;
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,8 @@ public final class LimboPlayerMatchers {
|
|||
description.appendText("Limbo with location = null");
|
||||
} else {
|
||||
description.appendText(format("Limbo with location: world=%s, x=%f, y=%f, z=%f",
|
||||
location.getWorld().getName(), location.getX(), location.getY(), location.getZ()));
|
||||
location.getWorld() != null ? location.getWorld().getName() : "N/D",
|
||||
location.getX(), location.getY(), location.getZ()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -89,7 +90,8 @@ public final class LimboPlayerMatchers {
|
|||
@Override
|
||||
protected boolean matchesSafely(LimboPlayer item) {
|
||||
Location location = item.getLocation();
|
||||
return hasLocation(location.getWorld(), location.getX(), location.getY(), location.getZ()).matches(item)
|
||||
return location.getWorld() != null
|
||||
&& hasLocation(location.getWorld(), location.getX(), location.getY(), location.getZ()).matches(item)
|
||||
&& location.getYaw() == yaw && location.getPitch() == pitch;
|
||||
}
|
||||
|
||||
|
@ -106,16 +108,16 @@ public final class LimboPlayerMatchers {
|
|||
description.appendText("Limbo with location = null");
|
||||
} else {
|
||||
description.appendText(format("Limbo with location: world=%s, x=%f, y=%f, z=%f, yaw=%f, pitch=%f",
|
||||
location.getWorld().getName(), location.getX(), location.getY(), location.getZ(),
|
||||
location.getYaw(), location.getPitch()));
|
||||
location.getWorld() != null ? location.getWorld().getName() : "N/D",
|
||||
location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Matcher<LimboPlayer> hasLocation(Location location) {
|
||||
return hasLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(),
|
||||
location.getYaw(), location.getPitch());
|
||||
return hasLocation(location.getWorld() != null ? location.getWorld().getName() : null,
|
||||
location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
// Hamcrest's contains() doesn't like it when there are no items, so we need to check for the empty case explicitly
|
||||
|
|
|
@ -3,13 +3,13 @@ package fr.xephi.authme.data.limbo.persistence;
|
|||
import ch.jalu.injector.testing.BeforeInjecting;
|
||||
import ch.jalu.injector.testing.DelayedInjectionRunner;
|
||||
import ch.jalu.injector.testing.InjectDelayed;
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.TestHelper;
|
||||
import fr.xephi.authme.data.limbo.LimboPlayer;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.LimboSettings;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -23,6 +23,9 @@ import org.mockito.Mock;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -72,6 +75,7 @@ public class DistributedFilesPersistenceHandlerTest {
|
|||
private static final UUID UNKNOWN_UUID2 = fromString("84d1cc0b-8f12-d04a-e7ba-a067d05cdc39");
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@InjectDelayed
|
||||
private DistributedFilesPersistenceHandler persistenceHandler;
|
||||
|
||||
|
@ -79,6 +83,7 @@ public class DistributedFilesPersistenceHandlerTest {
|
|||
private Settings settings;
|
||||
@Mock
|
||||
private BukkitService bukkitService;
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
@DataFolder
|
||||
private File dataFolder;
|
||||
private File playerDataFolder;
|
||||
|
@ -96,12 +101,12 @@ public class DistributedFilesPersistenceHandlerTest {
|
|||
given(settings.getProperty(LimboSettings.DISTRIBUTION_SIZE)).willReturn(SegmentSize.SIXTEEN);
|
||||
dataFolder = temporaryFolder.newFolder();
|
||||
playerDataFolder = new File(dataFolder, "playerdata");
|
||||
playerDataFolder.mkdir();
|
||||
FileUtils.createDirectoryOrFail(playerDataFolder);
|
||||
|
||||
File limboFilesFolder = new File(TEST_RESOURCES_FOLDER + PROJECT_ROOT + "data/limbo");
|
||||
for (File file : limboFilesFolder.listFiles()) {
|
||||
File from = new File(playerDataFolder, file.getName());
|
||||
Files.copy(file, from);
|
||||
Files.copy(file.toPath(), from.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
given(bukkitService.getWorld(anyString()))
|
||||
|
@ -185,7 +190,7 @@ public class DistributedFilesPersistenceHandlerTest {
|
|||
// assumption
|
||||
File invalidFile = new File(playerDataFolder, "seg16-4-limbo.json");
|
||||
assertThat(invalidFile.exists(), equalTo(false));
|
||||
Files.write("not valid json".getBytes(), invalidFile);
|
||||
Files.write(invalidFile.toPath(), "not valid json".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// when
|
||||
LimboPlayer result = persistenceHandler.getLimboPlayer(mockPlayerWithUuid(UNKNOWN_UUID));
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.mockito.Mock;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -60,7 +61,7 @@ public class IndividualFilesPersistenceHandlerTest {
|
|||
throw new IllegalStateException("Cannot create '" + playerFolder.getAbsolutePath() + "'");
|
||||
}
|
||||
Files.copy(TestHelper.getJarPath(FileUtils.makePath(SOURCE_FOLDER, "sample-folder", "data.json")),
|
||||
new File(playerFolder, "data.json").toPath());
|
||||
new File(playerFolder, "data.json").toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue