From 7f9d641fe3d6814a49869fa7044c22edaa846ee2 Mon Sep 17 00:00:00 2001
From: Gabriele C
Date: Sun, 6 Sep 2015 14:16:57 +0200
Subject: [PATCH 01/10] Fix hikari logger
---
pom.xml | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/pom.xml b/pom.xml
index 7182eff48..b34222f3e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,6 +89,7 @@
com.zaxxer:HikariCP
org.slf4j:slf4j-simple
+ org.slf4j:slf4j-api
com.maxmind.geoip:geoip-api
com.sun.mail:javax.mail
com.comphenix.attribute:AttributeStorage
@@ -195,6 +196,18 @@
2.4.1
compile
+
+ org.slf4j
+ slf4j-api
+ 1.7.12
+ compile
+
+
+ org.slf4j
+ slf4j-simple
+ 1.7.12
+ compile
+
From 495dd35b4848f1585858b62e3b2711d3f9dbb22d Mon Sep 17 00:00:00 2001
From: DmitryRendov
Date: Sun, 6 Sep 2015 20:28:25 +0000
Subject: [PATCH 02/10] Updated PBKDF2 hasher to support Django 1.7+
---
.../xephi/authme/security/crypts/CryptPBKDF2.java | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
index e6fb9bc50..426b36ee0 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
@@ -4,17 +4,18 @@ import java.security.NoSuchAlgorithmException;
import fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
+import javax.xml.bind.DatatypeConverter;
public class CryptPBKDF2 implements EncryptionMethod {
@Override
public String getHash(String password, String salt, String name)
throws NoSuchAlgorithmException {
- String result = "pbkdf2_sha256$10000$" + salt + "$";
- PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000);
+ String result = "pbkdf2_sha256$15000$" + salt + "$";
+ PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000);
PBKDF2Engine engine = new PBKDF2Engine(params);
-
- return result + String.valueOf(engine.deriveKey(password, 64));
+
+ return result + String.valueOf(DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32)));
}
@Override
@@ -22,8 +23,8 @@ public class CryptPBKDF2 implements EncryptionMethod {
String playerName) throws NoSuchAlgorithmException {
String[] line = hash.split("\\$");
String salt = line[2];
- String derivedKey = line[3];
- PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000, derivedKey.getBytes());
+ byte[] derivedKey = DatatypeConverter.parseBase64Binary(line[3]);
+ PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000, derivedKey);
PBKDF2Engine engine = new PBKDF2Engine(params);
return engine.verifyKey(password);
}
From 7c2649abf51ed388805d89b4b2541454a27c4189 Mon Sep 17 00:00:00 2001
From: DmitryRendov
Date: Sun, 6 Sep 2015 20:32:58 +0000
Subject: [PATCH 03/10] Fix
---
src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
index 426b36ee0..7e672ea79 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
@@ -14,7 +14,7 @@ public class CryptPBKDF2 implements EncryptionMethod {
String result = "pbkdf2_sha256$15000$" + salt + "$";
PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000);
PBKDF2Engine engine = new PBKDF2Engine(params);
-
+
return result + String.valueOf(DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32)));
}
From 395a514778b3afd7bd67c656c2345f5c1a6352b9 Mon Sep 17 00:00:00 2001
From: Alexandre Vanhecke
Date: Mon, 7 Sep 2015 12:33:24 +0200
Subject: [PATCH 04/10] Update README.md
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index 2f12855f9..02e6a9d36 100644
--- a/README.md
+++ b/README.md
@@ -125,6 +125,10 @@ typing commands or use the inventory. It can also kick players with uncommon lon
EUR:
USD:
+#####Sponsor
+GameHosting.it is leader in Italy in Game Server Provider. With its own DataCenter offers Anti-DDoS solutions at affordable prices. Game Server of Minecraft based on Multicraft are equipped with the latest technology in hardware.
+[![GameHosting](http://www.gamehosting.it/images/bn3.png)](http://www.gamehosting.it)
+
#####Credits
Team members: Xephi(Main Developer, Author), Maxetto(Contributor) and sgdc3(Contributor)
Credit for old version of the plugin to: d4rkwarriors, fabe1337 , Whoami2 and pomo4ka
From 1e9d7f879aad97c8f89f58f3c00644b37309b23c Mon Sep 17 00:00:00 2001
From: Alexandre Vanhecke
Date: Mon, 7 Sep 2015 12:35:49 +0200
Subject: [PATCH 05/10] Sponsor
---
src/main/java/fr/xephi/authme/AuthMe.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java
index 7ed3dd9f4..08ab36a5d 100644
--- a/src/main/java/fr/xephi/authme/AuthMe.java
+++ b/src/main/java/fr/xephi/authme/AuthMe.java
@@ -295,6 +295,7 @@ public class AuthMe extends JavaPlugin {
// Sponsor message
ConsoleLogger.info("AuthMe hooks perfectly with the VERYGAMES server hosting!");
+ ConsoleLogger.info("AuthMe builds are available on jenkins, thanks to our sponsor GameHosting.it - leader in Italy in Game Server Provider");
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " correctly enabled!");
}
From 8ec497a5e832459161426be79850fbee77552203 Mon Sep 17 00:00:00 2001
From: "Gabriele C."
Date: Mon, 7 Sep 2015 13:25:40 +0200
Subject: [PATCH 06/10] Update AuthMe.java
---
src/main/java/fr/xephi/authme/AuthMe.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java
index 7a817213a..5e6e2cc07 100644
--- a/src/main/java/fr/xephi/authme/AuthMe.java
+++ b/src/main/java/fr/xephi/authme/AuthMe.java
@@ -308,7 +308,7 @@ public class AuthMe extends JavaPlugin {
// Sponsor message
ConsoleLogger.info("AuthMe hooks perfectly with the VERYGAMES server hosting!");
- ConsoleLogger.info("AuthMe builds are available on jenkins, thanks to our sponsor GameHosting.it - leader in Italy in Game Server Provider");
+ ConsoleLogger.info("Development builds are available on our jenkins, thanks to our sponsor GameHosting.it - leader in Italy as Game Server Provider");
ConsoleLogger.info("AuthMe " + this.getDescription().getVersion() + " correctly enabled!");
}
From 0bab99b2fdf2fd92a21429fcc3e0d8cd2ac94480 Mon Sep 17 00:00:00 2001
From: "Gabriele C."
Date: Mon, 7 Sep 2015 13:29:22 +0200
Subject: [PATCH 07/10] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 02e6a9d36..3f12a0cc4 100644
--- a/README.md
+++ b/README.md
@@ -126,7 +126,7 @@ EUR:
#####Sponsor
-GameHosting.it is leader in Italy in Game Server Provider. With its own DataCenter offers Anti-DDoS solutions at affordable prices. Game Server of Minecraft based on Multicraft are equipped with the latest technology in hardware.
+GameHosting.it is leader in Italy as Game Server Provider. With its own DataCenter offers Anti-DDoS solutions at affordable prices. Game Server of Minecraft based on Multicraft are equipped with the latest technology in hardware.
[![GameHosting](http://www.gamehosting.it/images/bn3.png)](http://www.gamehosting.it)
#####Credits
From 84b5dcc62583f0827988413c74d95931b3f6fa4c Mon Sep 17 00:00:00 2001
From: Gabriele C
Date: Mon, 7 Sep 2015 14:05:50 +0200
Subject: [PATCH 08/10] Cleanup
---
src/main/java/fr/xephi/authme/AuthMe.java | 3 +-
.../fr/xephi/authme/datasource/MySQL.java | 10 +---
.../authme/datasource/SQLite_HIKARI.java | 55 ++++++++-----------
3 files changed, 26 insertions(+), 42 deletions(-)
diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java
index 131991dcf..353c96198 100644
--- a/src/main/java/fr/xephi/authme/AuthMe.java
+++ b/src/main/java/fr/xephi/authme/AuthMe.java
@@ -231,8 +231,9 @@ public class AuthMe extends JavaPlugin {
dataManager = new DataManager(this);
- // Setup API
+ // Setup the new API
api = new NewAPI(this);
+ // Old deprecated API
new API(this);
// Setup Management
diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java
index 24e37dbcd..594d489f9 100644
--- a/src/main/java/fr/xephi/authme/datasource/MySQL.java
+++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java
@@ -154,15 +154,9 @@ public class MySQL implements DataSource {
ConsoleLogger.info("Hikari ConnectionPool arguments reloaded!");
}
- private synchronized Connection getConnection() {
+ private synchronized Connection getConnection() throws SQLException {
Connection con = null;
- while(con == null){
- try {
- con = ds.getConnection();
- } catch (SQLException ce) {
- return null;
- }
- }
+ con = ds.getConnection();
return con;
}
diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite_HIKARI.java b/src/main/java/fr/xephi/authme/datasource/SQLite_HIKARI.java
index 2b6ea3869..9ac800553 100644
--- a/src/main/java/fr/xephi/authme/datasource/SQLite_HIKARI.java
+++ b/src/main/java/fr/xephi/authme/datasource/SQLite_HIKARI.java
@@ -100,7 +100,7 @@ public class SQLite_HIKARI implements DataSource {
this.setupConnection();
} catch (SQLException e) {
ConsoleLogger.showError(e.getMessage());
- ConsoleLogger.showError("Can't initialize the MySQL database... Please check your database settings in the config.yml file! SHUTDOWN...");
+ ConsoleLogger.showError("Can't initialize the SQLite database... Please check your database settings in the config.yml file! SHUTDOWN...");
ConsoleLogger.showError("If this error persists, please report it to the developer! SHUTDOWN...");
this.close();
if (Settings.isStopEnabled) {
@@ -133,30 +133,18 @@ public class SQLite_HIKARI implements DataSource {
ConsoleLogger.info("Connection arguments loaded, Hikari ConnectionPool ready!");
}
- private synchronized Connection getRawConnection() {
- Connection con = null;
- while(con == null){
- try {
- con = ds.getConnection();
- } catch (SQLException ce) {
- return null;
- }
+ private synchronized void reloadArguments()
+ throws ClassNotFoundException, IllegalArgumentException {
+ if (ds != null){
+ ds.close();
}
- return con;
+ setConnectionArguments();
+ ConsoleLogger.info("Hikari ConnectionPool arguments reloaded!");
}
- private synchronized Connection getConnection() {
- Connection con;
- con = getRawConnection();
- if(con == null){
- ds.close();
- ConsoleLogger.showError("Database connection is LOST! SHUTDOWN...");
- if (Settings.isStopEnabled) {
- AuthMe.getInstance().getServer().shutdown();
- } else {
- AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance());
- }
- }
+ private synchronized Connection getConnection() throws SQLException {
+ Connection con = null;
+ con = ds.getConnection();
return con;
}
@@ -165,17 +153,7 @@ public class SQLite_HIKARI implements DataSource {
Statement st = null;
ResultSet rs = null;
try {
- con = getRawConnection();
- if(con == null){
- ds.close();
- if (Settings.isStopEnabled) {
- ConsoleLogger.showError("Can't connect to the SQLite database... Please check your database settings in the config.yml file! SHUTDOWN...");
- AuthMe.getInstance().getServer().shutdown();
- } else {
- AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance());
- }
- return;
- }
+ con = getConnection();
st = con.createStatement();
st.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " (" + columnID + " INTEGER AUTO_INCREMENT," + columnName + " VARCHAR(255) NOT NULL UNIQUE," + columnPassword + " VARCHAR(255) NOT NULL," + columnIp + " VARCHAR(40) NOT NULL," + columnLastLogin + " BIGINT," + lastlocX + " DOUBLE NOT NULL DEFAULT '0.0'," + lastlocY + " DOUBLE NOT NULL DEFAULT '0.0'," + lastlocZ + " DOUBLE NOT NULL DEFAULT '0.0'," + lastlocWorld + " VARCHAR(255) NOT NULL DEFAULT '" + Settings.defaultWorld + "'," + columnEmail + " VARCHAR(255) DEFAULT 'your@email.com'," + "CONSTRAINT table_const_prim PRIMARY KEY (" + columnID + "));");
rs = con.getMetaData().getColumns(null, null, tableName, columnPassword);
@@ -807,6 +785,17 @@ public class SQLite_HIKARI implements DataSource {
@Override
public void reload() {
+ try {
+ reloadArguments();
+ } catch (Exception e) {
+ ConsoleLogger.showError(e.getMessage());
+ ConsoleLogger.showError("Can't reconnect to SQLite database... Please check your SQLite informations ! SHUTDOWN...");
+ if (Settings.isStopEnabled) {
+ AuthMe.getInstance().getServer().shutdown();
+ }
+ if (!Settings.isStopEnabled)
+ AuthMe.getInstance().getServer().getPluginManager().disablePlugin(AuthMe.getInstance());
+ }
}
@Override
From 65bb488f4cee61a60167f17bc723098867e68991 Mon Sep 17 00:00:00 2001
From: Gabriele C
Date: Mon, 7 Sep 2015 14:30:56 +0200
Subject: [PATCH 09/10] PBKDF2DJANGO Hash
---
.../xephi/authme/commands/AdminCommand.java | 3 ++
.../xephi/authme/security/HashAlgorithm.java | 1 +
.../authme/security/crypts/CryptPBKDF2.java | 13 ++++----
.../security/crypts/CryptPBKDF2Django.java | 32 +++++++++++++++++++
src/main/resources/config.yml | 2 +-
5 files changed, 43 insertions(+), 8 deletions(-)
create mode 100644 src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java
diff --git a/src/main/java/fr/xephi/authme/commands/AdminCommand.java b/src/main/java/fr/xephi/authme/commands/AdminCommand.java
index 1cc04829b..76269f8fd 100644
--- a/src/main/java/fr/xephi/authme/commands/AdminCommand.java
+++ b/src/main/java/fr/xephi/authme/commands/AdminCommand.java
@@ -520,6 +520,7 @@ public class AdminCommand implements CommandExecutor {
m.send(sender, "error");
return true;
}
+ @SuppressWarnings("deprecation")
Player target = Bukkit.getPlayer(name);
PlayerCache.getInstance().removePlayer(name);
Utils.getInstance().setGroup(name, groupType.UNREGISTERED);
@@ -602,6 +603,7 @@ public class AdminCommand implements CommandExecutor {
sender.sendMessage("Usage: /authme getip ");
return true;
}
+ @SuppressWarnings("deprecation")
Player player = Bukkit.getPlayer(args[1]);
if (player == null) {
sender.sendMessage("This player is not actually online");
@@ -617,6 +619,7 @@ public class AdminCommand implements CommandExecutor {
return true;
}
try {
+ @SuppressWarnings("deprecation")
Player player = Bukkit.getPlayer(args[1]);
if (player == null || !player.isOnline()) {
sender.sendMessage("Player needs to be online!");
diff --git a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java
index 312b6df01..935c9c1c1 100644
--- a/src/main/java/fr/xephi/authme/security/HashAlgorithm.java
+++ b/src/main/java/fr/xephi/authme/security/HashAlgorithm.java
@@ -25,6 +25,7 @@ public enum HashAlgorithm {
SHA512(fr.xephi.authme.security.crypts.SHA512.class),
DOUBLEMD5(fr.xephi.authme.security.crypts.DOUBLEMD5.class),
PBKDF2(fr.xephi.authme.security.crypts.CryptPBKDF2.class),
+ PBKDF2DJANGO(fr.xephi.authme.security.crypts.CryptPBKDF2Django.class),
WORDPRESS(fr.xephi.authme.security.crypts.WORDPRESS.class),
ROYALAUTH(fr.xephi.authme.security.crypts.ROYALAUTH.class),
CRAZYCRYPT1(fr.xephi.authme.security.crypts.CRAZYCRYPT1.class),
diff --git a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
index 7e672ea79..2914e47c8 100644
--- a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
+++ b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2.java
@@ -4,18 +4,17 @@ import java.security.NoSuchAlgorithmException;
import fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
-import javax.xml.bind.DatatypeConverter;
public class CryptPBKDF2 implements EncryptionMethod {
@Override
public String getHash(String password, String salt, String name)
throws NoSuchAlgorithmException {
- String result = "pbkdf2_sha256$15000$" + salt + "$";
- PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000);
+ String result = "pbkdf2_sha256$10000$" + salt + "$";
+ PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000);
PBKDF2Engine engine = new PBKDF2Engine(params);
- return result + String.valueOf(DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32)));
+ return result + String.valueOf(engine.deriveKey(password, 64));
}
@Override
@@ -23,10 +22,10 @@ public class CryptPBKDF2 implements EncryptionMethod {
String playerName) throws NoSuchAlgorithmException {
String[] line = hash.split("\\$");
String salt = line[2];
- byte[] derivedKey = DatatypeConverter.parseBase64Binary(line[3]);
- PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000, derivedKey);
+ String derivedKey = line[3];
+ PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 10000, derivedKey.getBytes());
PBKDF2Engine engine = new PBKDF2Engine(params);
return engine.verifyKey(password);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java
new file mode 100644
index 000000000..fc9986649
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/security/crypts/CryptPBKDF2Django.java
@@ -0,0 +1,32 @@
+package fr.xephi.authme.security.crypts;
+
+import java.security.NoSuchAlgorithmException;
+
+import fr.xephi.authme.security.pbkdf2.PBKDF2Engine;
+import fr.xephi.authme.security.pbkdf2.PBKDF2Parameters;
+import javax.xml.bind.DatatypeConverter;
+
+public class CryptPBKDF2Django implements EncryptionMethod {
+
+ @Override
+ public String getHash(String password, String salt, String name)
+ throws NoSuchAlgorithmException {
+ String result = "pbkdf2_sha256$15000$" + salt + "$";
+ PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000);
+ PBKDF2Engine engine = new PBKDF2Engine(params);
+
+ return result + String.valueOf(DatatypeConverter.printBase64Binary(engine.deriveKey(password, 32)));
+ }
+
+ @Override
+ public boolean comparePassword(String hash, String password,
+ String playerName) throws NoSuchAlgorithmException {
+ String[] line = hash.split("\\$");
+ String salt = line[2];
+ byte[] derivedKey = DatatypeConverter.parseBase64Binary(line[3]);
+ PBKDF2Parameters params = new PBKDF2Parameters("HmacSHA256", "ASCII", salt.getBytes(), 15000, derivedKey);
+ PBKDF2Engine engine = new PBKDF2Engine(params);
+ return engine.verifyKey(password);
+ }
+
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 89f16d2c2..768ce22f3 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -200,7 +200,7 @@ settings:
# possible values: MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB,
# PLAINTEXT ( unhashed password),
# MYBB, IPB3, PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512,
- # DOUBLEMD5, PBKDF2, WORDPRESS, ROYALAUTH, CUSTOM(for developpers only)
+ # DOUBLEMD5, PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM(for developpers only)
passwordHash: SHA256
# salt length for the SALTED2MD5 MD5(MD5(password)+salt)
doubleMD5SaltLength: 8
From 7a82bb7ba8366c27d4c3f33105d62f70d59dbbed Mon Sep 17 00:00:00 2001
From: "Gabriele C."
Date: Mon, 7 Sep 2015 15:41:22 +0200
Subject: [PATCH 10/10] Update team.txt
---
team.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/team.txt b/team.txt
index 634bcee58..e5ac3a1a6 100644
--- a/team.txt
+++ b/team.txt
@@ -3,6 +3,7 @@ AuthMe-Team:
Xephi (Xephi59) - Leader, Main developer
darkwarriors (d4rkwarriors) - Old AuthMe Reloaded Author
Kloudy - Developer (Inactive, Will be avariable soon)
+DNx5 - Developer
Gabriele C. (sgdc3) - Ticket Manager, Project Page and Structure Manager, Contributor
Maxetto - Ticket Manager, Italian Translator, Basic Developer, Contributor
Gnat008 - Contributor