· 9 years ago · Mar 12, 2017, 02:28 AM
1package org.stonecipher.plugins.token;
2
3import java.io.File;
4import java.sql.Connection;
5import java.sql.DriverManager;
6import java.sql.PreparedStatement;
7import java.sql.ResultSet;
8import java.sql.SQLException;
9import java.util.Random;
10
11import org.bukkit.plugin.java.JavaPlugin;
12import org.bukkit.command.Command;
13import org.bukkit.command.CommandSender;
14import org.bukkit.configuration.file.FileConfiguration;
15import org.bukkit.entity.Player;
16import org.bukkit.event.Listener;
17
18public class Main extends JavaPlugin implements Listener{
19
20 Random rand = new Random();
21
22 FileConfiguration config = getConfig();
23
24 // Database configuration
25 final private String username = config.getString("username");
26 final private String password = config.getString("password");
27 final private String url = "jdbc:mysql://" + config.getString("host") + "/" + config.getString("database");
28 static private Connection conn;
29
30 // Upon enable
31 @Override
32 public void onEnable() {
33
34 // Only attempts to connect to the database if
35 setupConfig();
36 if (!username.equals("username")){
37 connectToDatabase();
38 removeOutdatedTokens();
39 }
40
41 }
42
43 // Upon disable
44 @Override
45 public void onDisable() {
46
47 if (!username.equals("username")) {
48 removeOutdatedTokens();
49 disconnectFromDatabase();
50 }
51
52 }
53
54 // Command execution
55 @Override
56 public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
57 if (sender instanceof Player){
58 Player player = (Player) sender; // Create new player object
59 String uuid = player.getUniqueId().toString(); // Fetch UUID
60 String token = setToken(uuid);
61 if (token!="fail"){ // Set token in the database, returns true upon success
62 sender.sendMessage("§8[§7Token§8] §rYour token is §e" + token);
63 } else { // Upon token generation failure
64 sender.sendMessage("§8[§7Token§8] §rAn error occured, please contact your system administrator.");
65 }
66 return true;
67 } else {
68 sender.sendMessage("§8[§7Token§8] §rThis command can only be ran in-game");
69 }
70 return true;
71 }
72
73 // Sets up the config properly
74 private void setupConfig(){
75 try {
76 if (!getDataFolder().exists()) {
77 getDataFolder().mkdirs();
78 }
79 File file = new File(getDataFolder(), "config.yml");
80
81 if (!file.exists()) {
82 getLogger().info("Config.yml not found, creating!");
83 getLogger().info("You need to stop the server to edit the config then restart!");
84 saveDefaultConfig();
85 } else {
86 config.addDefault("database", "database");
87 config.addDefault("username", "username");
88 config.addDefault("password", "password");
89 config.addDefault("host", "localhost:3306");
90 config.addDefault("timeout", "1800");
91 config.addDefault("length", "8");
92 config.options().copyDefaults(true);
93 saveConfig();
94 getLogger().info("Config.yml found, loading!");
95 getLogger().info("Database: " + config.getString("database"));
96 getLogger().info("Username: " + config.getString("username"));
97 getLogger().info("Token Timeout: " + config.getString("timeout"));
98 getLogger().info("Token Length: " + config.getString("length"));
99 }
100 } catch (Exception e) {
101 e.printStackTrace();
102 }
103 }
104
105 // Safely connects to the database and sets up the table if it isn't set
106 private void connectToDatabase() {
107 try {
108 conn = DriverManager.getConnection(url, username, password);
109 String createTable = "CREATE TABLE IF NOT EXISTS tokens (token VARCHAR(16), uuid VARCHAR(32), time INT, UNIQUE KEY(uuid));";
110 try {
111 PreparedStatement table = conn.prepareStatement(createTable);
112 table.executeUpdate();
113 } catch (Exception e) {
114 e.printStackTrace();
115 }
116 } catch (SQLException e) {
117 e.printStackTrace();
118 }
119 }
120
121 // Safely disconnects from the database
122 private void disconnectFromDatabase(){
123 try {
124 if(conn!=null && !conn.isClosed()){
125 conn.close();
126 }
127 } catch (Exception e) {
128 e.printStackTrace();
129 }
130 }
131
132 // Removes tokens older than 30 minutes
133 private void removeOutdatedTokens() {
134 try {
135 String removeOldTokens = "DELETE FROM tokens WHERE time < (UNIX_TIMESTAMP()-?);";
136 PreparedStatement removeOldTokensPrepared = conn.prepareStatement(removeOldTokens);
137 removeOldTokensPrepared.setString(1, config.getString("timeout"));
138 removeOldTokensPrepared.executeUpdate();
139 } catch (Exception e) {
140 e.printStackTrace();
141 }
142 }
143
144 //REPLACE INTO the database so UUIDs don't get repeated
145 private boolean setUserToken(String uuid, String token) {
146 try {
147 String insertToken = "REPLACE INTO tokens(token, uuid, time) VALUES (?, ?, UNIX_TIMESTAMP());";
148 PreparedStatement insertTokenPrepared = conn.prepareStatement(insertToken);
149 insertTokenPrepared.setString(1, token);
150 insertTokenPrepared.setString(2, uuid);
151 insertTokenPrepared.executeUpdate();
152 return true;
153 } catch (Exception e) {
154 e.printStackTrace();
155 return false;
156 }
157 }
158
159 // Sets the token
160 private String setToken(String uuid) {
161 uuid = uuid.replace("-", ""); // Removes the dashed from the UUID for VARCHAR(32)
162 removeOutdatedTokens();
163 String token = generateUniqueToken();
164 if(setUserToken(uuid, token)){
165 return token;
166 } else {
167 return "fail";
168 }
169
170 }
171
172 // Checks if the token exists or not
173 private boolean tokenExists(String token) {
174 try{
175 String tokenCheck = "SELECT EXISTS(SELECT * FROM tokens WHERE token=?);";
176 PreparedStatement tokenCheckPrepared = conn.prepareStatement(tokenCheck);
177 tokenCheckPrepared.setString(1,token);
178 ResultSet result = tokenCheckPrepared.executeQuery();
179 result.first();
180 return result.getBoolean(1);
181 } catch (Exception e) {
182 e.printStackTrace();
183 }
184 return false;
185 }
186
187 // Continually generates a token until the token is unique
188 private String generateUniqueToken() {
189 while(true) {
190 String token = generateToken();
191 if(!tokenExists(token)) {
192 return token;
193 }
194 }
195 }
196
197 // Simple utility to randomly create a token
198 private String generateToken() {
199 // Simple random token generator. Was relatively cheap compared to the apache.utils.random
200 String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
201 int length = Integer.valueOf(config.getString("length"));
202 StringBuilder random = new StringBuilder();
203 for (int i = 0; i < length; i++) {
204 random.append(chars.charAt(rand.nextInt(52)));
205 }
206 return random.toString();
207 }
208}