WIP cleanup (1/?)

This commit is contained in:
Gabriele C 2020-06-27 03:37:22 +02:00
parent 06be8ea6f4
commit 8ca3374c16
138 changed files with 650 additions and 1718 deletions

View File

@ -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"/>

View File

@ -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'

1
.gitignore vendored
View File

@ -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

25
.idea/misc.xml Normal file
View File

@ -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>

View File

@ -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)

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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 "-";
}
}
}

View File

@ -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 {
}
}
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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());
}

View File

@ -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]));
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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());

View File

@ -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);
}

View File

@ -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);

View File

@ -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"));

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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));

View File

@ -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();
}

View File

@ -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

View File

@ -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));
}

View File

@ -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;

View File

@ -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");
}
/**

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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 &lt; 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 &lt; 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 &lt; 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);
}
}

View File

@ -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))));
}

View File

@ -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;
}
}

View File

@ -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());

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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;

View File

@ -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:", "");

View File

@ -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);

View File

@ -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 "";
}
}

View File

@ -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);

View File

@ -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"),

View File

@ -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

View File

@ -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"

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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");
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -24,4 +24,5 @@ public final class UuidUtils {
return null;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -1,3 +1,4 @@
<!--suppress HtmlUnknownTag, CheckEmptyScriptTag -->
<h1>Dear <playername />,</h1>
<p>

View File

@ -1,3 +1,4 @@
<!--suppress HtmlUnknownTag, CheckEmptyScriptTag -->
<h1>
Dear <playername />,
</h1>

View File

@ -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());

View File

@ -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

View File

@ -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);

View File

@ -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<>();

View File

@ -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);

View File

@ -45,6 +45,7 @@ public class HasPermissionCheckerTest {
@Mock
private BukkitService bukkitService;
@SuppressWarnings("FuseStreamOperations")
@Test
public void shouldListAllPermissionNodeClasses() {
// given

View File

@ -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));

View File

@ -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);

View File

@ -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");

View File

@ -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

View File

@ -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));

View File

@ -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