diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..def5ba5
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+version: 2
+updates:
+
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+
+ - package-ecosystem: "gradle"
+ directory: "/"
+ schedule:
+ interval: "daily"
diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml
new file mode 100644
index 0000000..2e2bc29
--- /dev/null
+++ b/.github/workflows/build-and-publish.yml
@@ -0,0 +1,30 @@
+name: Build and Publish
+
+on:
+ push:
+ branches:
+ - main
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - main
+
+env:
+ TERM: xterm-256color
+
+jobs:
+ build-and-publish:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Build jar
+ run: make
+
+ - name: Release
+ uses: softprops/action-gh-release@v1
+ if: startsWith(github.ref, 'refs/tags/')
+ with:
+ files: build/libs/*.jar
diff --git a/Makefile b/Makefile
index 15ffb50..3e32137 100644
--- a/Makefile
+++ b/Makefile
@@ -10,11 +10,6 @@ build:
./gradlew build
-.PHONY: coveralls
-coveralls:
- ./gradlew jacocoTestReport coveralls
-
-
.PHONY: wrapper
wrapper:
./gradlew wrapper
diff --git a/README.md b/README.md
index a3011f0..ad70a71 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,4 @@
-# VotifierPlus
-Fork of votifier
+# SimplyVotifier
+
+SimplyVotifier is a simple and easy to use Votifier listener plugin for PaperMC/Folia servers, originally forked from
+[VotifierPlus](https://github.com/BenCodez/VotifierPlus) by BenCodez.
diff --git a/build.gradle b/build.gradle
index 1cfd81c..51830e7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,15 +25,9 @@ repositories {
maven {
url 'https://repo.papermc.io/repository/maven-public/'
}
- maven {
- url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/'
- }
maven {
url 'https://nexus.bencodez.com/repository/maven-public/'
}
- maven {
- url 'https://oss.sonatype.org/content/repositories/snapshots'
- }
maven {
url 'https://nexuslite.gcnt.net/repos/other/'
}
@@ -56,11 +50,6 @@ processResources {
shadowJar {
archiveClassifier.set('')
relocate 'com.bencodez.advancedcore', 'net.simplyvanilla.dependency.advancedcore'
- relocate 'net.pl3x.bukkit.chatapi', 'net.simplyvanilla.dependency.chatapi'
- relocate 'me.mrten.mysqlapi', 'net.simplyvanilla.dependency.mysqlapi'
- relocate 'com.zaxxer.HikariCP', 'net.simplyvanilla.dependency.hikaricp'
- relocate 'com.zaxxer.hikari', 'net.simplyvanilla.dependency.hikari'
- relocate 'org.bstats', 'net.simplyvanilla.dependency.bstats'
minimize {
dependencies {
exclude('com.google')
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 1af9e09..a80b22c 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
diff --git a/gradlew.bat b/gradlew.bat
index 93e3f59..7101f8e 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,92 +1,92 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%"=="" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%"=="" set DIRNAME=.
-@rem This is normally unused
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if %ERRORLEVEL% equ 0 goto execute
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto execute
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
-
-:end
-@rem End local scope for the variables with windows NT shell
-if %ERRORLEVEL% equ 0 goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-set EXIT_CODE=%ERRORLEVEL%
-if %EXIT_CODE% equ 0 set EXIT_CODE=1
-if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
-exit /b %EXIT_CODE%
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/src/main/java/com/vexsoftware/votifier/ForwardServer.java b/src/main/java/com/vexsoftware/votifier/ForwardServer.java
deleted file mode 100644
index 71d9563..0000000
--- a/src/main/java/com/vexsoftware/votifier/ForwardServer.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.vexsoftware.votifier;
-
-import lombok.Getter;
-
-public class ForwardServer {
- @Getter
- private String host;
- @Getter
- private int port;
- @Getter
- private String key;
- @Getter
- private boolean enabled;
-
- public ForwardServer(boolean enabled, String host, int port, String key) {
- this.enabled = enabled;
- this.host = host;
- this.port = port;
- this.key = key;
- }
-}
diff --git a/src/main/java/com/vexsoftware/votifier/VotifierPlus.java b/src/main/java/com/vexsoftware/votifier/VotifierPlus.java
deleted file mode 100644
index fe5b805..0000000
--- a/src/main/java/com/vexsoftware/votifier/VotifierPlus.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2012 Vex Software LLC
- * This file is part of Votifier.
- *
- * Votifier is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Votifier is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Votifier. If not, see .
- */
-
-package com.vexsoftware.votifier;
-
-import com.bencodez.advancedcore.folialib.FoliaLib;
-import java.io.File;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.URL;
-import java.security.CodeSource;
-import java.security.KeyPair;
-import java.util.ArrayList;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import org.bukkit.Bukkit;
-import org.bukkit.configuration.ConfigurationSection;
-import org.bukkit.configuration.file.YamlConfiguration;
-
-import com.bencodez.advancedcore.AdvancedCorePlugin;
-import com.bencodez.advancedcore.api.command.CommandHandler;
-import com.bencodez.advancedcore.api.metrics.BStatsMetrics;
-import com.bencodez.advancedcore.api.updater.Updater;
-import com.vexsoftware.votifier.commands.CommandLoader;
-import com.vexsoftware.votifier.commands.CommandVotifierPlus;
-import com.vexsoftware.votifier.commands.VotifierPlusTabCompleter;
-import com.vexsoftware.votifier.config.Config;
-import com.vexsoftware.votifier.crypto.RSAIO;
-import com.vexsoftware.votifier.crypto.RSAKeygen;
-import com.vexsoftware.votifier.model.Vote;
-import com.vexsoftware.votifier.model.VotifierEvent;
-import com.vexsoftware.votifier.net.VoteReceiver;
-
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * The main Votifier plugin class.
- *
- * @author Blake Beaupain
- * @author Kramer Campbell
- */
-public class VotifierPlus extends AdvancedCorePlugin {
-
- /** The Votifier instance. */
- private static VotifierPlus instance;
-
- @Getter
- private FoliaLib foliaLib;
-
- public Config config;
-
- @Getter
- @Setter
- private Updater updater;
-
- /** The vote receiver. */
- private VoteReceiver voteReceiver;
-
- /** The RSA key pair. */
- @Setter
- private KeyPair keyPair;
-
- @Getter
- private ArrayList commands = new ArrayList();
-
- @Override
- public void onPostLoad() {
- this.foliaLib = new FoliaLib(this);
-
- getCommand("votifierplus").setExecutor(new CommandVotifierPlus(this));
- getCommand("votifierplus").setTabCompleter(new VotifierPlusTabCompleter());
- CommandLoader.getInstance().loadCommands();
-
- File rsaDirectory = new File(getDataFolder() + "/rsa");
-
- /*
- * Create RSA directory and keys if it does not exist; otherwise, read keys.
- */
- try {
- if (!rsaDirectory.exists()) {
- rsaDirectory.mkdir();
- keyPair = RSAKeygen.generate(2048);
- RSAIO.save(rsaDirectory, keyPair);
- } else {
- keyPair = RSAIO.load(rsaDirectory);
- }
- } catch (Exception ex) {
- getLogger().severe("Error reading configuration file or RSA keys");
- gracefulExit();
- return;
- }
-
- loadVoteReceiver();
-
- metrics();
- }
-
- private void loadVoteReceiver() {
- try {
- voteReceiver = new VoteReceiver(config.getHost(), config.getPort()) {
-
- @Override
- public void logWarning(String warn) {
- getLogger().warning(warn);
- }
-
- @Override
- public void logSevere(String msg) {
- getLogger().severe(msg);
- }
-
- @Override
- public void log(String msg) {
- getLogger().info(msg);
- }
-
- @Override
- public String getVersion() {
- return getDescription().getVersion();
- }
-
- @Override
- public Set getServers() {
- return config.getServers();
- }
-
- @Override
- public ForwardServer getServerData(String s) {
- ConfigurationSection d = config.getForwardingConfiguration(s);
- return new ForwardServer(d.getBoolean("Enabled"), d.getString("Host", ""), d.getInt("Port"),
- d.getString("Key", ""));
- }
-
- @Override
- public KeyPair getKeyPair() {
- return instance.getKeyPair();
- }
-
- @Override
- public void debug(Exception e) {
- instance.debug(e);
- }
-
- @Override
- public void debug(String debug) {
- instance.debug(debug);
- }
-
- @Override
- public void callEvent(Vote vote) {
- foliaLib.getImpl().runAsync(new Runnable() {
- public void run() {
- Bukkit.getServer().getPluginManager().callEvent(new VotifierEvent(vote));
- }
- });
- }
- };
- voteReceiver.start();
-
- getLogger().info("Votifier enabled.");
- } catch (Exception ex) {
- gracefulExit();
- return;
- }
- }
-
- @Override
- public void onDisable() {
- // Interrupt the vote receiver.
- if (voteReceiver != null) {
- voteReceiver.shutdown();
- }
- getLogger().info("Votifier disabled.");
- }
-
- private void gracefulExit() {
- getLogger().severe("Votifier did not initialize properly!");
- }
-
- /**
- * Gets the instance.
- *
- * @return The instance
- */
- public static VotifierPlus getInstance() {
- return instance;
- }
-
- /**
- * Gets the vote receiver.
- *
- * @return The vote receiver
- */
- public VoteReceiver getVoteReceiver() {
- return voteReceiver;
- }
-
- /**
- * Gets the keyPair.
- *
- * @return The keyPair
- */
- public KeyPair getKeyPair() {
- return keyPair;
- }
-
- @Override
- public void onPreLoad() {
- instance = this;
-
- config = new Config(this);
- config.setup();
-
- if (config.isJustCreated()) {
- int openPort = 8192;
- try {
- ServerSocket s = new ServerSocket();
- s.bind(new InetSocketAddress("0.0.0.0", 0));
- openPort = s.getLocalPort();
- s.close();
- } catch (Exception e) {
-
- }
- try {
- // First time run - do some initialization.
- getLogger().info("Configuring Votifier for the first time...");
- config.getData().set("port", openPort);
- config.saveData();
-
- /*
- * Remind hosted server admins to be sure they have the right port number.
- */
- getLogger().info("------------------------------------------------------------------------------");
- getLogger().info("Assigning Votifier to listen on an open port " + openPort
- + ". If you are hosting server on a");
- getLogger().info("shared server please check with your hosting provider to verify that this port");
- getLogger().info("is available for your use. Chances are that your hosting provider will assign");
- getLogger().info("a different port, which you need to specify in config.yml");
- getLogger().info("------------------------------------------------------------------------------");
-
- } catch (Exception ex) {
- getLogger().severe("Error creating configuration file");
- debug(ex);
- }
- }
- config.loadValues();
-
- updateAdvancedCoreHook();
- }
-
- private void metrics() {
- BStatsMetrics metrics = new BStatsMetrics(this, 5807);
- metrics.addCustomChart(new BStatsMetrics.SimplePie("Forwarding", new Callable() {
-
- @Override
- public String call() throws Exception {
- int amount = 0;
- for (String server : config.getServers()) {
- if (config.getForwardingConfiguration(server).getBoolean("Enabled")) {
- amount++;
- }
- }
- return "" + amount;
- }
- }));
- }
-
- @Override
- public void onUnLoad() {
-
- }
-
- @Override
- public void reload() {
- config.reloadData();
- updateAdvancedCoreHook();
- voteReceiver.shutdown();
- loadVoteReceiver();
- }
-
- @SuppressWarnings("deprecation")
- public void updateAdvancedCoreHook() {
- setConfigData(config.getData());
- setLoadRewards(false);
- setLoadServerData(false);
- setLoadUserData(false);
- setLoadGeyserAPI(false);
- setLoadLuckPerms(false);
- }
-
-}
diff --git a/src/main/java/com/vexsoftware/votifier/commands/CommandLoader.java b/src/main/java/com/vexsoftware/votifier/commands/CommandLoader.java
deleted file mode 100644
index 30e4e9b..0000000
--- a/src/main/java/com/vexsoftware/votifier/commands/CommandLoader.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.vexsoftware.votifier.commands;
-
-import java.io.File;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.security.PublicKey;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-
-import org.bukkit.command.CommandSender;
-
-import com.bencodez.advancedcore.api.command.CommandHandler;
-import com.vexsoftware.votifier.VotifierPlus;
-import com.vexsoftware.votifier.crypto.RSAIO;
-import com.vexsoftware.votifier.crypto.RSAKeygen;
-
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.chat.TextComponent;
-
-// TODO: Auto-generated Javadoc
-/**
- * The Class CommandLoader.
- */
-public class CommandLoader {
-
- private static CommandLoader instance = new CommandLoader();
- private VotifierPlus plugin = VotifierPlus.getInstance();
-
- public static CommandLoader getInstance() {
- return instance;
- }
-
- public ArrayList helpText(CommandSender sender) {
- ArrayList msg = new ArrayList();
- HashMap unsorted = new HashMap();
-
- boolean requirePerms = false;
- ChatColor hoverColor = ChatColor.AQUA;
- for (CommandHandler cmdHandle : plugin.getCommands()) {
- if (!requirePerms || cmdHandle.hasPerm(sender)) {
- unsorted.put(cmdHandle.getHelpLineCommand("/votifierplus"),
- cmdHandle.getHelpLine("/votifierplus", "&6%Command% - &6%HelpMessage%", hoverColor));
- }
- }
- ArrayList unsortedList = new ArrayList();
- unsortedList.addAll(unsorted.keySet());
- Collections.sort(unsortedList, String.CASE_INSENSITIVE_ORDER);
- for (String cmd : unsortedList) {
- msg.add(unsorted.get(cmd));
- }
-
- return msg;
- }
-
- public void loadCommands() {
- plugin.getCommands()
- .add(new CommandHandler(plugin, new String[] { "Help" }, "VotifierPlus.Help", "Open help page") {
-
- @Override
- public void execute(CommandSender sender, String[] args) {
- sendMessageJson(sender, helpText(sender));
- }
- });
- plugin.getCommands()
- .add(new CommandHandler(plugin, new String[] { "Reload" }, "VotifierPlus.Reload", "Reload the plugin") {
-
- @Override
- public void execute(CommandSender sender, String[] args) {
- plugin.reload();
- sendMessage(sender, "&cVotifierPlus " + plugin.getVersion() + " reloaded");
- }
- });
-
- plugin.getCommands().add(new CommandHandler(plugin, new String[] { "GenerateKeys" },
- "VotifierPlus.GenerateKeys", "Regenerate votifier keys", true, true) {
-
- @Override
- public void execute(CommandSender sender, String[] args) {
- File rsaDirectory = new File(plugin.getDataFolder() + File.separator + "rsa");
-
- try {
- for (File file : rsaDirectory.listFiles()) {
- if (!file.isDirectory()) {
- file.delete();
- }
- }
- rsaDirectory.mkdir();
- plugin.setKeyPair(RSAKeygen.generate(2048));
- RSAIO.save(rsaDirectory, plugin.getKeyPair());
- } catch (Exception ex) {
- sendMessage(sender, "&cFailed to create keys");
- return;
- }
- sendMessage(sender, "&cNew keys generated");
- }
- });
-
- plugin.getCommands().add(new CommandHandler(plugin, new String[] { "Test", "(player)", "(Text)" },
- "VotifierPlus.Test", "Test votifier connection") {
-
- @Override
- public void execute(CommandSender sender, String[] args) {
- try {
- PublicKey publicKey = plugin.getKeyPair().getPublic();
- String serverIP = plugin.config.getHost();
- int serverPort = plugin.config.getPort();
- if (serverIP.length() != 0) {
- String VoteString = "VOTE\n" + args[2] + "\n" + args[1] + "\n" + "Address" + "\n" + "TestVote"
- + "\n";
-
- SocketAddress sockAddr = new InetSocketAddress(serverIP, serverPort);
- Socket socket1 = new Socket();
- socket1.connect(sockAddr, 1000);
- OutputStream socketOutputStream = socket1.getOutputStream();
- socketOutputStream.write(plugin.getVoteReceiver().encrypt(VoteString.getBytes(), publicKey));
- socketOutputStream.close();
- socket1.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- sendMessage(sender, "&cCheck console for test results");
-
- }
- });
- }
-}
diff --git a/src/main/java/com/vexsoftware/votifier/commands/CommandVotifierPlus.java b/src/main/java/com/vexsoftware/votifier/commands/CommandVotifierPlus.java
deleted file mode 100644
index 2ad7123..0000000
--- a/src/main/java/com/vexsoftware/votifier/commands/CommandVotifierPlus.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.vexsoftware.votifier.commands;
-
-import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
-import org.bukkit.command.CommandSender;
-
-import com.bencodez.advancedcore.api.command.CommandHandler;
-import com.vexsoftware.votifier.VotifierPlus;
-
-// TODO: Auto-generated Javadoc
-/**
- * The Class CommandVotifierPlus.
- */
-public class CommandVotifierPlus implements CommandExecutor {
- /** The plugin. */
- private VotifierPlus plugin;
-
- /**
- * Instantiates a new command vote.
- *
- * @param plugin
- * the plugin
- */
- public CommandVotifierPlus(VotifierPlus plugin) {
- this.plugin = plugin;
- }
-
- /*
- * (non-Javadoc)
- * @see org.bukkit.command.CommandExecutor#onCommand(org.bukkit.command.
- * CommandSender , org.bukkit.command.Command, java.lang.String,
- * java.lang.String[])
- */
- @Override
- public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
-
- for (CommandHandler commandHandler : plugin.getCommands()) {
- if (commandHandler.runCommand(sender, args)) {
- return true;
- }
- }
-
- // invalid command
- sender.sendMessage(ChatColor.RED + "No valid arguments, see /votifierplus help!");
- return true;
- }
-
-}
diff --git a/src/main/java/com/vexsoftware/votifier/commands/VotifierPlusTabCompleter.java b/src/main/java/com/vexsoftware/votifier/commands/VotifierPlusTabCompleter.java
deleted file mode 100644
index 01f824b..0000000
--- a/src/main/java/com/vexsoftware/votifier/commands/VotifierPlusTabCompleter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.vexsoftware.votifier.commands;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.TabCompleter;
-
-import com.bencodez.advancedcore.api.command.TabCompleteHandler;
-import com.bencodez.advancedcore.api.messages.StringParser;
-import com.vexsoftware.votifier.VotifierPlus;
-
-// TODO: Auto-generated Javadoc
-/**
- * The Class VoteTabCompleter.
- */
-public class VotifierPlusTabCompleter implements TabCompleter {
-
- /*
- * (non-Javadoc)
- * @see org.bukkit.command.TabCompleter#onTabComplete(org.bukkit.command.
- * CommandSender, org.bukkit.command.Command, java.lang.String,
- * java.lang.String[])
- */
- @Override
- public List onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) {
-
- ArrayList tab = new ArrayList();
-
- Set cmds = new HashSet();
-
- cmds.addAll(TabCompleteHandler.getInstance().getTabCompleteOptions(VotifierPlus.getInstance().getCommands(),
- sender, args, args.length - 1));
-
- for (String str : cmds) {
- if (StringParser.getInstance().startsWithIgnoreCase(str, args[args.length - 1])) {
- tab.add(str);
- }
- }
-
- Collections.sort(tab, String.CASE_INSENSITIVE_ORDER);
-
- return tab;
- }
-
-}
diff --git a/src/main/java/com/vexsoftware/votifier/config/Config.java b/src/main/java/com/vexsoftware/votifier/config/Config.java
deleted file mode 100644
index f7c57ee..0000000
--- a/src/main/java/com/vexsoftware/votifier/config/Config.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.vexsoftware.votifier.config;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.bukkit.configuration.ConfigurationSection;
-
-import com.bencodez.advancedcore.api.yml.YMLFile;
-import com.bencodez.advancedcore.api.yml.annotation.AnnotationHandler;
-import com.bencodez.advancedcore.api.yml.annotation.ConfigDataBoolean;
-import com.bencodez.advancedcore.api.yml.annotation.ConfigDataInt;
-import com.bencodez.advancedcore.api.yml.annotation.ConfigDataKeys;
-import com.bencodez.advancedcore.api.yml.annotation.ConfigDataString;
-import com.vexsoftware.votifier.VotifierPlus;
-
-import lombok.Getter;
-import lombok.Setter;
-
-public class Config extends YMLFile {
-
- public Config(VotifierPlus plugin) {
- super(plugin, new File(VotifierPlus.getInstance().getDataFolder(), "config.yml"));
- }
-
- public void loadValues() {
- new AnnotationHandler().load(getData(), this);
- }
-
- @Override
- public void onFileCreation() {
- VotifierPlus.getInstance().saveResource("config.yml", true);
- }
-
- @ConfigDataString(path = "host")
- @Getter
- @Setter
- private String host = "0.0.0.0";
-
- @ConfigDataInt(path = "port")
- @Getter
- @Setter
- private int port = 8192;
-
- @ConfigDataBoolean(path = "debug")
- @Getter
- @Setter
- private boolean debug = false;
-
- @ConfigDataKeys(path = "Forwarding")
- @Getter
- @Setter
- private Set servers = new HashSet();
-
- @ConfigDataBoolean(path = "DisableUpdateChecking")
- @Getter
- private boolean disableUpdateChecking = false;
-
- public ConfigurationSection getForwardingConfiguration(String s) {
- return getData().getConfigurationSection("Forwarding." + s);
- }
-
-}
diff --git a/src/main/java/com/vexsoftware/votifier/crypto/RSAIO.java b/src/main/java/com/vexsoftware/votifier/crypto/RSAIO.java
deleted file mode 100644
index fff6dd1..0000000
--- a/src/main/java/com/vexsoftware/votifier/crypto/RSAIO.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2011 Vex Software LLC
- * This file is part of Votifier.
- *
- * Votifier is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Votifier is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Votifier. If not, see .
- */
-
-package com.vexsoftware.votifier.crypto;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.Base64;
-
-/**
- * Static utility methods for saving and loading RSA key pairs.
- *
- * @author Blake Beaupain
- */
-public class RSAIO {
-
- /**
- * Saves the key pair to the disk.
- *
- * @param directory
- * The directory to save to
- * @param keyPair
- * The key pair to save
- * @throws Exception
- * If an error occurs
- */
- public static void save(File directory, KeyPair keyPair) throws Exception {
- PrivateKey privateKey = keyPair.getPrivate();
- PublicKey publicKey = keyPair.getPublic();
-
- // Store the public key.
- X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(publicKey.getEncoded());
- FileOutputStream out = null;
- try {
- out = new FileOutputStream(directory + "/public.key");
- out.write(Base64.getEncoder().encodeToString(publicSpec.getEncoded()).getBytes());
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (out != null) {
- out.close();
- }
- }
- // out.close();
-
- // Store the private key.
- PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
- try {
- out = new FileOutputStream(directory + "/private.key");
- out.write(Base64.getEncoder().encodeToString(privateSpec.getEncoded()).getBytes());
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (out != null) {
- out.close();
- }
- }
- }
-
- /**
- * Loads an RSA key pair from a directory. The directory must have the files
- * "public.key" and "private.key".
- *
- * @param directory
- * The directory to load from
- * @return The key pair
- * @throws Exception
- * If an error occurs
- */
- public static KeyPair load(File directory) throws Exception {
- // Read the public key file.
- File publicKeyFile = new File(directory + "/public.key");
- byte[] encodedPublicKey = null;
- try (FileInputStream in = new FileInputStream(publicKeyFile)) {
- encodedPublicKey = new byte[(int) publicKeyFile.length()];
- in.read(encodedPublicKey);
- encodedPublicKey = Base64.getDecoder().decode(encodedPublicKey);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- // Read the private key file.
- File privateKeyFile = new File(directory + "/private.key");
- byte[] encodedPrivateKey = null;
- try (FileInputStream in = new FileInputStream(privateKeyFile)) {
- encodedPrivateKey = new byte[(int) privateKeyFile.length()];
- in.read(encodedPrivateKey);
- encodedPrivateKey = Base64.getDecoder().decode(encodedPrivateKey);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- // Instantiate and return the key pair.
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
- PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
- PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
- PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
- return new KeyPair(publicKey, privateKey);
- }
-
-}
diff --git a/src/main/java/com/vexsoftware/votifier/model/Vote.java b/src/main/java/com/vexsoftware/votifier/model/Vote.java
deleted file mode 100644
index c8ef4b0..0000000
--- a/src/main/java/com/vexsoftware/votifier/model/Vote.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2011 Vex Software LLC
- * This file is part of Votifier.
- *
- * Votifier is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Votifier is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Votifier. If not, see .
- */
-
-package com.vexsoftware.votifier.model;
-
-/**
- * A model for a vote.
- *
- * @author Blake Beaupain
- */
-public class Vote {
-
- /** The name of the vote service. */
- private String serviceName;
-
- /** The username of the voter. */
- private String username;
-
- /** The address of the voter. */
- private String address;
-
- /** The date and time of the vote. */
- private String timeStamp;
-
- @Override
- public String toString() {
- return "Vote (from:" + serviceName + " username:" + username
- + " address:" + address + " timeStamp:" + timeStamp + ")";
- }
-
- /**
- * Sets the serviceName.
- *
- * @param serviceName
- * The new serviceName
- */
- public void setServiceName(String serviceName) {
- this.serviceName = serviceName;
- }
-
- /**
- * Gets the serviceName.
- *
- * @return The serviceName
- */
- public String getServiceName() {
- return serviceName;
- }
-
- /**
- * Sets the username.
- *
- * @param username
- * The new username
- */
- public void setUsername(String username) {
- this.username = username.length() <= 16 ? username : username.substring(0, 16);
- }
-
- /**
- * Gets the username.
- *
- * @return The username
- */
- public String getUsername() {
- return username;
- }
-
- /**
- * Sets the address.
- *
- * @param address
- * The new address
- */
- public void setAddress(String address) {
- this.address = address;
- }
-
- /**
- * Gets the address.
- *
- * @return The address
- */
- public String getAddress() {
- return address;
- }
-
- /**
- * Sets the time stamp.
- *
- * @param timeStamp
- * The new time stamp
- */
- public void setTimeStamp(String timeStamp) {
- this.timeStamp = timeStamp;
- }
-
- /**
- * Gets the time stamp.
- *
- * @return The time stamp
- */
- public String getTimeStamp() {
- return timeStamp;
- }
-
-}
diff --git a/src/main/java/com/vexsoftware/votifier/model/VotifierEvent.java b/src/main/java/com/vexsoftware/votifier/model/VotifierEvent.java
deleted file mode 100644
index 0e8cbc7..0000000
--- a/src/main/java/com/vexsoftware/votifier/model/VotifierEvent.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.vexsoftware.votifier.model;
-
-import org.bukkit.event.*;
-
-/**
- * {@code VotifierEvent} is a custom Bukkit event class that is sent
- * synchronously to CraftBukkit's main thread allowing other plugins to listener
- * for votes.
- *
- * @author frelling
- *
- */
-public class VotifierEvent extends Event {
- /**
- * Event listener handler list.
- */
- private static final HandlerList handlers = new HandlerList();
-
- /**
- * Encapsulated vote record.
- */
- private Vote vote;
-
- /**
- * Constructs a vote event that encapsulated the given vote record.
- *
- * @param vote
- * vote record
- */
- public VotifierEvent(final Vote vote) {
- this.vote = vote;
- }
-
- /**
- * Return the encapsulated vote record.
- *
- * @return vote record
- */
- public Vote getVote() {
- return vote;
- }
-
- @Override
- public HandlerList getHandlers() {
- return handlers;
- }
-
- public static HandlerList getHandlerList() {
- return handlers;
- }
-}
diff --git a/src/main/java/com/vexsoftware/votifier/net/VoteReceiver.java b/src/main/java/com/vexsoftware/votifier/net/VoteReceiver.java
deleted file mode 100644
index 305d5fc..0000000
--- a/src/main/java/com/vexsoftware/votifier/net/VoteReceiver.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2012 Vex Software LLC
- * This file is part of Votifier.
- *
- * Votifier is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Votifier is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Votifier. If not, see .
- */
-
-package com.vexsoftware.votifier.net;
-
-import java.io.BufferedWriter;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.PublicKey;
-import java.security.spec.X509EncodedKeySpec;
-import java.util.Base64;
-import java.util.Set;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-
-import com.vexsoftware.votifier.ForwardServer;
-import com.vexsoftware.votifier.crypto.RSA;
-import com.vexsoftware.votifier.model.Vote;
-
-/**
- * The vote receiving server.
- *
- * @author Blake Beaupain
- * @author Kramer Campbell
- */
-public abstract class VoteReceiver extends Thread {
-
- /** The host to listen on. */
- private final String host;
-
- /** The port to listen on. */
- private final int port;
-
- /** The server socket. */
- private ServerSocket server;
-
- /** The running flag. */
- private boolean running = true;
-
- /**
- * Instantiates a new vote receiver
- *
- * @param host
- * The host to listen on
- * @param port
- * The port to listen on
- * @throws Exception
- * exception
- */
- public VoteReceiver(String host, int port) throws Exception {
- super("Votifier I/O");
- this.host = host;
- this.port = port;
-
- setPriority(Thread.MIN_PRIORITY);
-
- initialize();
- }
-
- private void initialize() throws Exception {
- try {
- server = new ServerSocket();
- server.bind(new InetSocketAddress(host, port));
- debug(server.getInetAddress().getHostAddress() + ":" + server.getLocalPort());
- } catch (Exception ex) {
- logSevere("Error initializing vote receiver. Please verify that the configured");
- logSevere("IP address and port are not already in use. This is a common problem");
- logSevere("with hosting services and, if so, you should check with your hosting provider.");
- ex.printStackTrace();
- throw new Exception(ex);
- }
- }
-
- public abstract void logWarning(String warn);
-
- public abstract void logSevere(String msg);
-
- public abstract void log(String msg);
-
- public abstract void debug(String debug);
-
- public abstract String getVersion();
-
- /**
- * Shuts the vote receiver down cleanly.
- */
- public void shutdown() {
- running = false;
- if (server == null)
- return;
- try {
- server.close();
- } catch (Exception ex) {
- logWarning("Unable to shut down vote receiver cleanly.");
- }
- }
-
- public abstract Set getServers();
-
- public abstract KeyPair getKeyPair();
-
- @Override
- public void run() {
-
- // Main loop.
- while (running) {
- try (Socket socket = server.accept()) {
- socket.setSoTimeout(5000); // Don't hang on slow connections.
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
- InputStream in = socket.getInputStream();
-
- // Send them our version.
- writer.write("VOTIFIERPLUS " + getVersion());
- writer.newLine();
- writer.flush();
-
- // Read the 256 byte block.
- byte[] block = new byte[256];
- in.read(block, 0, block.length);
-
- // Decrypt the block.
- block = RSA.decrypt(block, getKeyPair().getPrivate());
- int position = 0;
-
- // Perform the opcode check.
- String opcode = readString(block, position);
- position += opcode.length() + 1;
- if (!opcode.equals("VOTE")) {
- // Something went wrong in RSA.
- throw new Exception("Unable to decode RSA");
- }
-
- // Parse the block.
- String serviceName = readString(block, position);
- position += serviceName.length() + 1;
- String username = readString(block, position);
- position += username.length() + 1;
- String address = readString(block, position);
- position += address.length() + 1;
- String timeStamp = readString(block, position);
- position += timeStamp.length() + 1;
-
- // Create the vote.
- final Vote vote = new Vote();
- vote.setServiceName(serviceName);
- vote.setUsername(username);
- vote.setAddress(address);
- vote.setTimeStamp(timeStamp);
-
- if (timeStamp.equalsIgnoreCase("TestVote")) {
- log("Test vote received");
- }
-
- debug("Received vote record -> " + vote);
-
- for (String server : getServers()) {
- ForwardServer forwardServer = getServerData(server);
- if (forwardServer.isEnabled()) {
- debug("Sending vote to " + server);
-
- byte[] encodedPublicKey = Base64.getDecoder().decode(forwardServer.getKey());
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
- PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
- String serverIP = forwardServer.getHost();
- int serverPort = forwardServer.getPort();
- if (serverIP.length() != 0) {
- try {
- String VoteString = "VOTE\n" + vote.getServiceName() + "\n" + vote.getUsername() + "\n"
- + vote.getAddress() + "\n" + vote.getTimeStamp() + "\n";
-
- SocketAddress sockAddr = new InetSocketAddress(serverIP, serverPort);
- Socket socket1 = new Socket();
- socket1.connect(sockAddr, 1000);
- OutputStream socketOutputStream = socket1.getOutputStream();
- socketOutputStream.write(encrypt(VoteString.getBytes(), publicKey));
- socketOutputStream.close();
- socket1.close();
-
- } catch (Exception e) {
- log("Failed to send vote to " + server + "(" + serverIP + ":" + serverPort + "): "
- + vote.toString() + ", ignore this if server is offline. Enable debug to see the stacktrace");
- debug(e);
- }
- }
-
- }
- }
-
- // Call event in a synchronized fashion to ensure that the
- // custom event runs in the
- // the main server thread, not this one.
- callEvent(vote);
-
- // Clean up.
- writer.close();
- in.close();
- socket.close();
- } catch (SocketException ex) {
- logWarning("Protocol error. Ignoring packet - " + ex.getLocalizedMessage());
- debug(ex);
- } catch (BadPaddingException ex) {
- logWarning("Unable to decrypt vote record. Make sure that that your public key");
- logWarning("matches the one you gave the server list.");
- debug(ex);
- } catch (Exception ex) {
- logWarning("Exception caught while receiving a vote notification");
- debug(ex);
- }
- }
-
- }
-
- public abstract ForwardServer getServerData(String s);
-
- public abstract void debug(Exception e);
-
- public abstract void callEvent(Vote e);
-
- public byte[] encrypt(byte[] data, PublicKey key) throws Exception {
- Cipher cipher = Cipher.getInstance("RSA");
- cipher.init(Cipher.ENCRYPT_MODE, key);
- return cipher.doFinal(data);
- }
-
- /**
- * Reads a string from a block of data.
- *
- * @param data
- * The data to read from
- * @return The string
- */
- private String readString(byte[] data, int offset) {
- StringBuilder builder = new StringBuilder();
- for (int i = offset; i < data.length; i++) {
- if (data[i] == '\n')
- break; // Delimiter reached.
- builder.append((char) data[i]);
- }
- return builder.toString();
- }
-}
diff --git a/src/main/java/net/simplyvanilla/simplyvotifier/SimplyVotifier.java b/src/main/java/net/simplyvanilla/simplyvotifier/SimplyVotifier.java
new file mode 100644
index 0000000..ee3183d
--- /dev/null
+++ b/src/main/java/net/simplyvanilla/simplyvotifier/SimplyVotifier.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2012 Vex Software LLC
+ * This file is part of Votifier.
+ *
+ * Votifier is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Votifier is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Votifier. If not, see .
+ */
+
+package net.simplyvanilla.simplyvotifier;
+
+import com.bencodez.advancedcore.AdvancedCorePlugin;
+import com.bencodez.advancedcore.folialib.FoliaLib;
+import lombok.Getter;
+import lombok.Setter;
+import net.simplyvanilla.simplyvotifier.config.Config;
+import net.simplyvanilla.simplyvotifier.crypto.RSAIO;
+import net.simplyvanilla.simplyvotifier.crypto.RSAKeygen;
+import net.simplyvanilla.simplyvotifier.model.Vote;
+import net.simplyvanilla.simplyvotifier.model.VotifierEvent;
+import net.simplyvanilla.simplyvotifier.net.VoteReceiver;
+import org.bukkit.Bukkit;
+
+import java.io.File;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.security.KeyPair;
+
+/**
+ * The main Votifier plugin class.
+ *
+ * @author Blake Beaupain
+ * @author Kramer Campbell
+ */
+public class SimplyVotifier extends AdvancedCorePlugin {
+
+ /**
+ * The Votifier instance.
+ */
+ @Getter
+ private static SimplyVotifier instance;
+
+ @Getter
+ private FoliaLib foliaLib;
+
+ public Config config;
+
+ /**
+ * The vote receiver.
+ */
+ @Getter
+ private VoteReceiver voteReceiver;
+
+ /**
+ * The RSA key pair.
+ */
+ @Getter
+ @Setter
+ private KeyPair keyPair;
+
+
+ @Override
+ public void onPostLoad() {
+ this.foliaLib = new FoliaLib(this);
+
+ File rsaDirectory = new File(getDataFolder() + "/rsa");
+
+ /*
+ * Create RSA directory and keys if it does not exist; otherwise, read keys.
+ */
+ try {
+ if (!rsaDirectory.exists()) {
+ rsaDirectory.mkdir();
+ keyPair = RSAKeygen.generate(2048);
+ RSAIO.save(rsaDirectory, keyPair);
+ } else {
+ keyPair = RSAIO.load(rsaDirectory);
+ }
+ } catch (Exception ex) {
+ getLogger().severe("Error reading configuration file or RSA keys");
+ gracefulExit();
+ return;
+ }
+
+ loadVoteReceiver();
+ }
+
+ private void loadVoteReceiver() {
+ try {
+ voteReceiver = new VoteReceiver(config.getHost(), config.getPort()) {
+
+ @Override
+ public void logWarning(String warn) {
+ getLogger().warning(warn);
+ }
+
+ @Override
+ public void logSevere(String msg) {
+ getLogger().severe(msg);
+ }
+
+ @Override
+ public void log(String msg) {
+ getLogger().info(msg);
+ }
+
+ @Override
+ public String getVersion() {
+ return getDescription().getVersion();
+ }
+
+ @Override
+ public KeyPair getKeyPair() {
+ return instance.getKeyPair();
+ }
+
+ @Override
+ public void debug(Exception e) {
+ instance.debug(e);
+ }
+
+ @Override
+ public void debug(String debug) {
+ instance.debug(debug);
+ }
+
+ @Override
+ public void callEvent(Vote vote) {
+ foliaLib.getImpl().runAsync(new Runnable() {
+ public void run() {
+ Bukkit.getServer().getPluginManager().callEvent(new VotifierEvent(vote));
+ }
+ });
+ }
+ };
+ voteReceiver.start();
+
+ getLogger().info("Votifier enabled.");
+ } catch (Exception ex) {
+ gracefulExit();
+ return;
+ }
+ }
+
+ @Override
+ public void onDisable() {
+ // Interrupt the vote receiver.
+ if (voteReceiver != null) {
+ voteReceiver.shutdown();
+ }
+ getLogger().info("Votifier disabled.");
+ }
+
+ private void gracefulExit() {
+ getLogger().severe("Votifier did not initialize properly!");
+ }
+
+ @Override
+ public void onPreLoad() {
+ instance = this;
+
+ config = new Config(this);
+ config.setup();
+
+ if (config.isJustCreated()) {
+ int openPort = 8192;
+ try {
+ ServerSocket s = new ServerSocket();
+ s.bind(new InetSocketAddress("0.0.0.0", 0));
+ openPort = s.getLocalPort();
+ s.close();
+ } catch (Exception e) {
+
+ }
+ try {
+ // First time run - do some initialization.
+ getLogger().info("Configuring Votifier for the first time...");
+ config.getData().set("port", openPort);
+ config.saveData();
+
+ /*
+ * Remind hosted server admins to be sure they have the right port number.
+ */
+ getLogger().info("------------------------------------------------------------------------------");
+ getLogger().info("Assigning Votifier to listen on an open port " + openPort
+ + ". If you are hosting server on a");
+ getLogger().info("shared server please check with your hosting provider to verify that this port");
+ getLogger().info("is available for your use. Chances are that your hosting provider will assign");
+ getLogger().info("a different port, which you need to specify in config.yml");
+ getLogger().info("------------------------------------------------------------------------------");
+
+ } catch (Exception ex) {
+ getLogger().severe("Error creating configuration file");
+ debug(ex);
+ }
+ }
+ config.loadValues();
+
+ updateAdvancedCoreHook();
+ }
+
+ @Override
+ public void onUnLoad() {
+
+ }
+
+ @Override
+ public void reload() {
+ config.reloadData();
+ updateAdvancedCoreHook();
+ voteReceiver.shutdown();
+ loadVoteReceiver();
+ }
+
+ @SuppressWarnings("deprecation")
+ public void updateAdvancedCoreHook() {
+ setConfigData(config.getData());
+ setLoadRewards(false);
+ setLoadServerData(false);
+ setLoadUserData(false);
+ setLoadGeyserAPI(false);
+ setLoadLuckPerms(false);
+ }
+
+}
diff --git a/src/main/java/net/simplyvanilla/simplyvotifier/config/Config.java b/src/main/java/net/simplyvanilla/simplyvotifier/config/Config.java
new file mode 100644
index 0000000..6476708
--- /dev/null
+++ b/src/main/java/net/simplyvanilla/simplyvotifier/config/Config.java
@@ -0,0 +1,39 @@
+package net.simplyvanilla.simplyvotifier.config;
+
+import com.bencodez.advancedcore.api.yml.YMLFile;
+import com.bencodez.advancedcore.api.yml.annotation.AnnotationHandler;
+import com.bencodez.advancedcore.api.yml.annotation.ConfigDataBoolean;
+import com.bencodez.advancedcore.api.yml.annotation.ConfigDataInt;
+import com.bencodez.advancedcore.api.yml.annotation.ConfigDataString;
+import lombok.Getter;
+import lombok.Setter;
+import net.simplyvanilla.simplyvotifier.SimplyVotifier;
+
+import java.io.File;
+
+@Setter
+@Getter
+public class Config extends YMLFile {
+
+ public Config(SimplyVotifier plugin) {
+ super(plugin, new File(SimplyVotifier.getInstance().getDataFolder(), "config.yml"));
+ }
+
+ public void loadValues() {
+ new AnnotationHandler().load(getData(), this);
+ }
+
+ @Override
+ public void onFileCreation() {
+ SimplyVotifier.getInstance().saveResource("config.yml", true);
+ }
+
+ @ConfigDataString(path = "host")
+ private String host = "0.0.0.0";
+
+ @ConfigDataInt(path = "port")
+ private int port = 8192;
+
+ @ConfigDataBoolean(path = "debug")
+ private boolean debug = false;
+}
diff --git a/src/main/java/com/vexsoftware/votifier/crypto/RSA.java b/src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSA.java
similarity index 50%
rename from src/main/java/com/vexsoftware/votifier/crypto/RSA.java
rename to src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSA.java
index 41df187..5765c08 100644
--- a/src/main/java/com/vexsoftware/votifier/crypto/RSA.java
+++ b/src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSA.java
@@ -1,68 +1,61 @@
/*
* Copyright (C) 2011 Vex Software LLC
* This file is part of Votifier.
- *
+ *
* Votifier is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* Votifier is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with Votifier. If not, see .
*/
-package com.vexsoftware.votifier.crypto;
+package net.simplyvanilla.simplyvotifier.crypto;
+import javax.crypto.Cipher;
import java.security.PrivateKey;
import java.security.PublicKey;
-import javax.crypto.Cipher;
-
/**
* Static RSA utility methods for encrypting and decrypting blocks of
* information.
- *
+ *
* @author Blake Beaupain
*/
public class RSA {
- /**
- * Encrypts a block of data.
- *
- * @param data
- * The data to encrypt
- * @param key
- * The key to encrypt with
- * @return The encrypted data
- * @throws Exception
- * If an error occurs
- */
- public static byte[] encrypt(byte[] data, PublicKey key) throws Exception {
- Cipher cipher = Cipher.getInstance("RSA");
- cipher.init(Cipher.ENCRYPT_MODE, key);
- return cipher.doFinal(data);
- }
+ /**
+ * Encrypts a block of data.
+ *
+ * @param data The data to encrypt
+ * @param key The key to encrypt with
+ * @return The encrypted data
+ * @throws Exception If an error occurs
+ */
+ public static byte[] encrypt(byte[] data, PublicKey key) throws Exception {
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ return cipher.doFinal(data);
+ }
- /**
- * Decrypts a block of data.
- *
- * @param data
- * The data to decrypt
- * @param key
- * The key to decrypt with
- * @return The decrypted data
- * @throws Exception
- * If an error occurs
- */
- public static byte[] decrypt(byte[] data, PrivateKey key) throws Exception {
- Cipher cipher = Cipher.getInstance("RSA");
- cipher.init(Cipher.DECRYPT_MODE, key);
- return cipher.doFinal(data);
- }
+ /**
+ * Decrypts a block of data.
+ *
+ * @param data The data to decrypt
+ * @param key The key to decrypt with
+ * @return The decrypted data
+ * @throws Exception If an error occurs
+ */
+ public static byte[] decrypt(byte[] data, PrivateKey key) throws Exception {
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.DECRYPT_MODE, key);
+ return cipher.doFinal(data);
+ }
}
diff --git a/src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSAIO.java b/src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSAIO.java
new file mode 100644
index 0000000..e3e8385
--- /dev/null
+++ b/src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSAIO.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2011 Vex Software LLC
+ * This file is part of Votifier.
+ *
+ * Votifier is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Votifier is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Votifier. If not, see .
+ */
+
+package net.simplyvanilla.simplyvotifier.crypto;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+/**
+ * Static utility methods for saving and loading RSA key pairs.
+ *
+ * @author Blake Beaupain
+ */
+public class RSAIO {
+
+ /**
+ * Saves the key pair to the disk.
+ *
+ * @param directory The directory to save to
+ * @param keyPair The key pair to save
+ * @throws Exception If an error occurs
+ */
+ public static void save(File directory, KeyPair keyPair) throws Exception {
+ PrivateKey privateKey = keyPair.getPrivate();
+ PublicKey publicKey = keyPair.getPublic();
+
+ // Store the public key.
+ X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(publicKey.getEncoded());
+ FileOutputStream out = null;
+ try {
+ out = new FileOutputStream(directory + "/public.key");
+ out.write(Base64.getEncoder().encodeToString(publicSpec.getEncoded()).getBytes());
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ // out.close();
+
+ // Store the private key.
+ PKCS8EncodedKeySpec privateSpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
+ try {
+ out = new FileOutputStream(directory + "/private.key");
+ out.write(Base64.getEncoder().encodeToString(privateSpec.getEncoded()).getBytes());
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ }
+
+ /**
+ * Loads an RSA key pair from a directory. The directory must have the files
+ * "public.key" and "private.key".
+ *
+ * @param directory The directory to load from
+ * @return The key pair
+ * @throws Exception If an error occurs
+ */
+ public static KeyPair load(File directory) throws Exception {
+ // Read the public key file.
+ File publicKeyFile = new File(directory + "/public.key");
+ byte[] encodedPublicKey = null;
+ try (FileInputStream in = new FileInputStream(publicKeyFile)) {
+ encodedPublicKey = new byte[(int) publicKeyFile.length()];
+ in.read(encodedPublicKey);
+ encodedPublicKey = Base64.getDecoder().decode(encodedPublicKey);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ // Read the private key file.
+ File privateKeyFile = new File(directory + "/private.key");
+ byte[] encodedPrivateKey = null;
+ try (FileInputStream in = new FileInputStream(privateKeyFile)) {
+ encodedPrivateKey = new byte[(int) privateKeyFile.length()];
+ in.read(encodedPrivateKey);
+ encodedPrivateKey = Base64.getDecoder().decode(encodedPrivateKey);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ // Instantiate and return the key pair.
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedPublicKey);
+ PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+ PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
+ PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
+ return new KeyPair(publicKey, privateKey);
+ }
+
+}
diff --git a/src/main/java/com/vexsoftware/votifier/crypto/RSAKeygen.java b/src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSAKeygen.java
similarity index 63%
rename from src/main/java/com/vexsoftware/votifier/crypto/RSAKeygen.java
rename to src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSAKeygen.java
index 93c6cdf..a89373c 100644
--- a/src/main/java/com/vexsoftware/votifier/crypto/RSAKeygen.java
+++ b/src/main/java/net/simplyvanilla/simplyvotifier/crypto/RSAKeygen.java
@@ -1,22 +1,22 @@
/*
* Copyright (C) 2011 Vex Software LLC
* This file is part of Votifier.
- *
+ *
* Votifier is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* Votifier is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with Votifier. If not, see .
*/
-package com.vexsoftware.votifier.crypto;
+package net.simplyvanilla.simplyvotifier.crypto;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -24,25 +24,23 @@
/**
* An RSA key pair generator.
- *
+ *
* @author Blake Beaupain
*/
public abstract class RSAKeygen {
- /**
- * Generates an RSA key pair.
- *
- * @param bits
- * The amount of bits
- * @return The key pair
- * @throws Exception
- * exception
- */
- public static KeyPair generate(int bits) throws Exception {
- KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
- RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(bits, RSAKeyGenParameterSpec.F4);
- keygen.initialize(spec);
- return keygen.generateKeyPair();
- }
+ /**
+ * Generates an RSA key pair.
+ *
+ * @param bits The amount of bits
+ * @return The key pair
+ * @throws Exception exception
+ */
+ public static KeyPair generate(int bits) throws Exception {
+ KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
+ RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(bits, RSAKeyGenParameterSpec.F4);
+ keygen.initialize(spec);
+ return keygen.generateKeyPair();
+ }
}
diff --git a/src/main/java/net/simplyvanilla/simplyvotifier/model/Vote.java b/src/main/java/net/simplyvanilla/simplyvotifier/model/Vote.java
new file mode 100644
index 0000000..a8b6268
--- /dev/null
+++ b/src/main/java/net/simplyvanilla/simplyvotifier/model/Vote.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 Vex Software LLC
+ * This file is part of Votifier.
+ *
+ * Votifier is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Votifier is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Votifier. If not, see .
+ */
+
+package net.simplyvanilla.simplyvotifier.model;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * A model for a vote.
+ *
+ * @author Blake Beaupain
+ */
+@Getter
+public class Vote {
+
+ /**
+ * The name of the vote service.
+ */
+ @Setter
+ private String serviceName;
+
+ /**
+ * The username of the voter.
+ */
+ private String username;
+
+ /**
+ * The address of the voter.
+ */
+ @Setter
+ private String address;
+
+ /**
+ * The date and time of the vote.
+ */
+ @Setter
+ private String timeStamp;
+
+ @Override
+ public String toString() {
+ return "Vote (from:" + serviceName + " username:" + username
+ + " address:" + address + " timeStamp:" + timeStamp + ")";
+ }
+
+ /**
+ * Sets the username.
+ *
+ * @param username The new username
+ */
+ public void setUsername(String username) {
+ this.username = username.length() <= 16 ? username : username.substring(0, 16);
+ }
+
+}
diff --git a/src/main/java/net/simplyvanilla/simplyvotifier/model/VotifierEvent.java b/src/main/java/net/simplyvanilla/simplyvotifier/model/VotifierEvent.java
new file mode 100644
index 0000000..2984ff9
--- /dev/null
+++ b/src/main/java/net/simplyvanilla/simplyvotifier/model/VotifierEvent.java
@@ -0,0 +1,40 @@
+package net.simplyvanilla.simplyvotifier.model;
+
+import lombok.Getter;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+/**
+ * {@code VotifierEvent} is a custom Bukkit event class that is sent
+ * synchronously to CraftBukkit's main thread allowing other plugins to listener
+ * for votes.
+ *
+ * @author frelling
+ */
+@Getter
+public class VotifierEvent extends Event {
+ /**
+ * Event listener handler list.
+ */
+ private static final HandlerList handlers = new HandlerList();
+
+ /**
+ * Encapsulated vote record.
+ */
+ private Vote vote;
+
+ /**
+ * Constructs a vote event that encapsulated the given vote record.
+ *
+ * @param vote vote record
+ */
+ public VotifierEvent(final Vote vote) {
+ this.vote = vote;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+}
diff --git a/src/main/java/net/simplyvanilla/simplyvotifier/net/VoteReceiver.java b/src/main/java/net/simplyvanilla/simplyvotifier/net/VoteReceiver.java
new file mode 100644
index 0000000..ff5f6ec
--- /dev/null
+++ b/src/main/java/net/simplyvanilla/simplyvotifier/net/VoteReceiver.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2012 Vex Software LLC
+ * This file is part of Votifier.
+ *
+ * Votifier is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Votifier is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Votifier. If not, see .
+ */
+
+package net.simplyvanilla.simplyvotifier.net;
+
+import net.simplyvanilla.simplyvotifier.crypto.RSA;
+import net.simplyvanilla.simplyvotifier.model.Vote;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.security.KeyPair;
+import java.security.PublicKey;
+
+/**
+ * The vote receiving server.
+ *
+ * @author Blake Beaupain
+ * @author Kramer Campbell
+ */
+public abstract class VoteReceiver extends Thread {
+
+ /**
+ * The host to listen on.
+ */
+ private final String host;
+
+ /**
+ * The port to listen on.
+ */
+ private final int port;
+
+ /**
+ * The server socket.
+ */
+ private ServerSocket server;
+
+ /**
+ * The running flag.
+ */
+ private boolean running = true;
+
+ /**
+ * Instantiates a new vote receiver
+ *
+ * @param host The host to listen on
+ * @param port The port to listen on
+ * @throws Exception exception
+ */
+ public VoteReceiver(String host, int port) throws Exception {
+ super("Votifier I/O");
+ this.host = host;
+ this.port = port;
+
+ setPriority(Thread.MIN_PRIORITY);
+
+ initialize();
+ }
+
+ private void initialize() throws Exception {
+ try {
+ server = new ServerSocket();
+ server.bind(new InetSocketAddress(host, port));
+ debug(server.getInetAddress().getHostAddress() + ":" + server.getLocalPort());
+ } catch (Exception ex) {
+ logSevere("Error initializing vote receiver. Please verify that the configured");
+ logSevere("IP address and port are not already in use. This is a common problem");
+ logSevere("with hosting services and, if so, you should check with your hosting provider.");
+ ex.printStackTrace();
+ throw new Exception(ex);
+ }
+ }
+
+ public abstract void logWarning(String warn);
+
+ public abstract void logSevere(String msg);
+
+ public abstract void log(String msg);
+
+ public abstract void debug(String debug);
+
+ public abstract String getVersion();
+
+ /**
+ * Shuts the vote receiver down cleanly.
+ */
+ public void shutdown() {
+ running = false;
+ if (server == null)
+ return;
+ try {
+ server.close();
+ } catch (Exception ex) {
+ logWarning("Unable to shut down vote receiver cleanly.");
+ }
+ }
+
+ public abstract KeyPair getKeyPair();
+
+ @Override
+ public void run() {
+
+ // Main loop.
+ while (running) {
+ try (Socket socket = server.accept()) {
+ socket.setSoTimeout(5000); // Don't hang on slow connections.
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
+ InputStream in = socket.getInputStream();
+
+ // Send them our version.
+ writer.write("SIMPLYVOTIFIER " + getVersion());
+ writer.newLine();
+ writer.flush();
+
+ // Read the 256 byte block.
+ byte[] block = new byte[256];
+ in.read(block, 0, block.length);
+
+ // Decrypt the block.
+ block = RSA.decrypt(block, getKeyPair().getPrivate());
+ int position = 0;
+
+ // Perform the opcode check.
+ String opcode = readString(block, position);
+ position += opcode.length() + 1;
+ if (!opcode.equals("VOTE")) {
+ // Something went wrong in RSA.
+ throw new Exception("Unable to decode RSA");
+ }
+
+ // Parse the block.
+ String serviceName = readString(block, position);
+ position += serviceName.length() + 1;
+ String username = readString(block, position);
+ position += username.length() + 1;
+ String address = readString(block, position);
+ position += address.length() + 1;
+ String timeStamp = readString(block, position);
+ position += timeStamp.length() + 1;
+
+ // Create the vote.
+ final Vote vote = new Vote();
+ vote.setServiceName(serviceName);
+ vote.setUsername(username);
+ vote.setAddress(address);
+ vote.setTimeStamp(timeStamp);
+
+ if (timeStamp.equalsIgnoreCase("TestVote")) {
+ log("Test vote received");
+ }
+
+ debug("Received vote record -> " + vote);
+
+ // Call event in a synchronized fashion to ensure that the
+ // custom event runs in the
+ // the main server thread, not this one.
+ callEvent(vote);
+
+ // Clean up.
+ writer.close();
+ in.close();
+ socket.close();
+ } catch (SocketException ex) {
+ logWarning("Protocol error. Ignoring packet - " + ex.getLocalizedMessage());
+ debug(ex);
+ } catch (BadPaddingException ex) {
+ logWarning("Unable to decrypt vote record. Make sure that that your public key");
+ logWarning("matches the one you gave the server list.");
+ debug(ex);
+ } catch (Exception ex) {
+ logWarning("Exception caught while receiving a vote notification");
+ debug(ex);
+ }
+ }
+
+ }
+
+ public abstract void debug(Exception e);
+
+ public abstract void callEvent(Vote e);
+
+ public byte[] encrypt(byte[] data, PublicKey key) throws Exception {
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ return cipher.doFinal(data);
+ }
+
+ /**
+ * Reads a string from a block of data.
+ *
+ * @param data The data to read from
+ * @return The string
+ */
+ private String readString(byte[] data, int offset) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = offset; i < data.length; i++) {
+ if (data[i] == '\n')
+ break; // Delimiter reached.
+ builder.append((char) data[i]);
+ }
+ return builder.toString();
+ }
+}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index aa9ff19..2e22435 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -5,9 +5,3 @@
DebugLevel: NONE
host: 0.0.0.0
port: 8192
-Forwarding:
- server1:
- Enabled: false
- Host: ''
- Port: 8193
- Key: ''
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index fff12a7..8ad4c73 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,11 +1,9 @@
+main: net.simplyvanilla.simplyvotifier.SimplyVotifier
name: SimplyVotifier
-main: com.vexsoftware.votifier.VotifierPlus
-version: @version@
description: A plugin that gets notified when votes are made for the server on toplists.
-author: BenCodez
-api-version: 1.13
-softdepend: [SuperVanish, PremiumVanish]
+version: @version@
+api-version: 1.19
+
+author: Simply Vanilla
+website: https://github.com/SimplyVanilla/SimplyChat
folia-supported: true
-commands:
- votifierplus:
- description: main command