hockey did an oopsie

This commit is contained in:
Super_ 2019-01-22 07:40:17 -05:00
parent dded19e254
commit a6b278e7cb
15 changed files with 849 additions and 720 deletions

View File

@ -2,7 +2,7 @@
<artifact type="jar" build-on-make="true" name="Capatchafy">
<output-path>$PROJECT_DIR$/target/</output-path>
<root id="archive" name="Capatchafy.jar">
<element id="module-output" name="Capatchafy" />
<element id="module-output" name="Captchafy" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/org/glassfish/grizzly/grizzly-http-server/2.4.0/grizzly-http-server-2.4.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/commons-io/commons-io/2.6/commons-io-2.6.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/javax/annotation/javax.annotation-api/1.2/javax.annotation-api-1.2.jar" path-in-jar="/" />

View File

@ -6,7 +6,7 @@
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="Capatchafy" />
<module name="Captchafy" />
</profile>
</annotationProcessing>
</component>

View File

@ -8,7 +8,7 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="9" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

124
.idea/uiDesigner.xml Normal file
View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,44 +1,44 @@
# Capatchafy - The only spambot solution you'll ever need.
# Captchafy - The only spambot solution you'll ever need.
### What is Capatchafy?
Capatchafy is a Spigot plugin/extension for Minecraft servers. Its sole purpose is to protect against spambot attacks. When a server is under attack, Capatchafy directs players to solve a capatcha before joining. This prevents spambots from flooding and crashing a server. Attacks are automatically detected by Capatchafy, so you can kick back and let Capatchafy do the work.
### What is Captchafy?
Captchafy is a Spigot plugin/extension for Minecraft servers. Its sole purpose is to protect against spambot attacks. When a server is under attack, Captchafy directs players to solve a captcha before joining. This prevents spambots from flooding and crashing a server. Attacks are automatically detected by Captchafy, so you can kick back and let Captchafy do the work.
### How does Capatchafy work?
From a user's standpoint, during an attack, they will be kicked and ask to solve a capatcha at example.com:port/capatcha/. Once the capatcha is solved, their ip is added to a list of authorized IPs and they are allowed to join.
### How does Captchafy work?
From a user's standpoint, during an attack, they will be kicked and ask to solve a captcha at example.com:port/captcha/. Once the captcha is solved, their ip is added to a list of authorized IPs and they are allowed to join.
Capatchafy runs on a lightweight, embedded Grizzly container for Jersey. This allows us to make full use of the jax-rs API. When a player accesses the capatcha URL in their browser, they send an HTTP/GET request to the server, which is processed by Capatchafy. Capatchafy serves the user the capatcha. The player solves the capatcha. Their capatcha data is POSTed back to the server, and is then sent off to Google to be verified. Once Google gives the okay, the player's IP is added to the list of authorized IPs.
Captchafy runs on a lightweight, embedded Grizzly container for Jersey. This allows us to make full use of the jax-rs API. When a player accesses the captcha URL in their browser, they send an HTTP/GET request to the server, which is processed by Captchafy. Captchafy serves the user the captcha. The player solves the captcha. Their captcha data is POSTed back to the server, and is then sent off to Google to be verified. Once Google gives the okay, the player's IP is added to the list of authorized IPs.
### Features
- Capatcha-based Spam-bot Prevention.
- Captcha-based Spam-bot Prevention.
- IP Whitelisting
- Automatic Attack Detection
- Multiple Security Modes
- Check the Issues tab for more.
### How do I use Capatchafy?
Capatchafy comes with one simple command: /capatchafy.
### How do I use Captchafy?
Captchafy comes with one simple command: /captchafy.
Usage: /capatchafy <on:off> <friendly:moderate:strict> or /capatchafy <on:off> <1:2:3>
The on/off parameter will turn on/turn off Capatcha based verification. The second parameter is the security level.
Usage: /captchafy <on:off> <friendly:moderate:strict> or /captchafy <on:off> <1:2:3>
The on/off parameter will turn on/turn off Captcha based verification. The second parameter is the security level.
Security levels:
1/Friendly - Players will only have to solve a capatcha once. Their IPs will be saved in a config for future logins.
2/Moderate - Players will have to solve one capatcha every time the server reloads. (Recommended)
3/Strict - Players will have to solve a capatcha every time they join.
1/Friendly - Players will only have to solve a captcha once. Their IPs will be saved in a config for future logins.
2/Moderate - Players will have to solve one captcha every time the server reloads. (Recommended)
3/Strict - Players will have to solve a captcha every time they join.
Capatchafy will auto-enable/disable when the server is attacked. You can force Capatchafy to stay off by using the command /capatchafy off -f. Capatchafy will not auto-disable if you enable it using the command.
Captchafy will auto-enable/disable when the server is attacked. You can force Captchafy to stay off by using the command /captchafy off -f. Captchafy will not auto-disable if you enable it using the command.
You will need to assign the permission 'capatchafy.command' to anyone who needs to use /capatchafy. It is assigned to OPs by default.
You will need to assign the permission 'captchafy.command' to anyone who needs to use /captchafy. It is assigned to OPs by default.
You can also whitelist IPs in the config. These IPs will never have to solve a capatcha.
You can also whitelist IPs in the config. These IPs will never have to solve a captcha.
### How do I install Capatchafy?
Installation is fairly straight-forward. Drag Capatchafy to your plugins folder like any other add-on, and start your server. This will allow Capatchafy to generate the necessary config files. Then, edit the config as you please. You will need to obtain a reCapatcha key from Google. You can do that here: https://www.google.com/recaptcha/. Place the keys in the config file, and you're ready to go! Be sure to open a port up in your firewall, as well as port forward if you are creating a server on a home connection.
### How do I install Captchafy?
Installation is fairly straight-forward. Drag Captchafy to your plugins folder like any other add-on, and start your server. This will allow Captchafy to generate the necessary config files. Then, edit the config as you please. You will need to obtain a reCaptcha key from Google. You can do that here: https://www.google.com/recaptcha/. Place the keys in the config file, and you're ready to go! Be sure to open a port up in your firewall, as well as port forward if you are creating a server on a home connection.
---
### Compiling
Capatchafy makes use of Maven, so it should compile automatically. If you are using Intellij or Eclipse, you might need to run 'mvn package' in the command line to build the project. Netbeans does this for you. You shouldn't need to add any dependencies or make edits to the POM. However, you MUST use the jar labeled Capatchafy-jar-with-dependencies. If you don't, you will get NoClassDefFound errors. If you have any problems, open an issue.
Captchafy makes use of Maven, so it should compile automatically. If you are using Intellij or Eclipse, you might need to run 'mvn package' in the command line to build the project. Netbeans does this for you. You shouldn't need to add any dependencies or make edits to the POM. However, you MUST use the jar labeled Captchafy-jar-with-dependencies. If you don't, you will get NoClassDefFound errors. If you have any problems, open an issue.
### License
Capatchafy is licensed under the GNU General Public License v3.0. You can find a copy of it in the License.txt file.
Captchafy is licensed under the GNU General Public License v3.0. You can find a copy of it in the License.txt file.

View File

@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.hockey</groupId>
<artifactId>Capatchafy</artifactId>
<artifactId>Captchafy</artifactId>
<version>1.1.0</version>
<packaging>jar</packaging>
<properties>

View File

@ -1,96 +1,96 @@
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.capatchafy;
import me.hockey.capatchafy.httpd.HttpdServer;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.glassfish.grizzly.http.server.HttpServer;
import java.io.IOException;
public class Capatchafy extends JavaPlugin
{
public static Capatchafy plugin;
public static Listeners listeners;
public static Configuration configs;
public static boolean enabled = false;
public static boolean forced = false; //Disallows auto-enabling/disabling of capatchafy.
public static int securityLevel;
public HttpServer server;
public static boolean error = false;
@Override
public void onEnable()
{
plugin = this;
configs = new Configuration();
listeners = new Listeners();
listeners.setThrottleSettings();
Bukkit.getPluginManager().registerEvents(listeners, this);
getCommand("capatchafy").setExecutor(new CapatchafyCommand());
try
{
configs = new Configuration();
configs.startup();
if (configs.isIncomplete())
{
Bukkit.getLogger().severe("[Capatchafy] There is information missing in the config. Please make the appropriate changes. " +
"This is normal on the first run. Reload the server once you have made the correct edits.");
Capatchafy.error = true;
Bukkit.getPluginManager().disablePlugin(Capatchafy.plugin);
return;
}
}
catch (IOException e)
{
e.printStackTrace();
}
securityLevel = configs.config.getInt("security-level");
if (securityLevel > 3 || securityLevel < 1)
{
securityLevel = 2;
Bukkit.getLogger().severe("[Capatchafy] The 'security-level' config field was not between 1 and 3. Setting security level to 2.");
}
enabled = configs.config.getBoolean("always-on");
server = HttpdServer.getServer();
listeners.setURLMessage();
Bukkit.getLogger().info("[Capatchafy] Running in security level " + securityLevel + ".");
}
@Override
public void onDisable()
{
if (error)
{
return; //Prevents errors on the first startup.
}
try
{
configs.saveNames(true);
configs.saveConfig();
}
catch (IOException e)
{
e.printStackTrace();
}
server.shutdownNow();
configs.ipList.clear(); //TODO See if removing this line affects functionality.
}
}
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.captchafy;
import me.hockey.captchafy.httpd.HttpdServer;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.glassfish.grizzly.http.server.HttpServer;
import java.io.IOException;
public class Captchafy extends JavaPlugin
{
public static Captchafy plugin;
public static Listeners listeners;
public static Configuration configs;
public static boolean enabled = false;
public static boolean forced = false; //Disallows auto-enabling/disabling of captchafy.
public static int securityLevel;
public HttpServer server;
public static boolean error = false;
@Override
public void onEnable()
{
plugin = this;
configs = new Configuration();
listeners = new Listeners();
listeners.setThrottleSettings();
Bukkit.getPluginManager().registerEvents(listeners, this);
getCommand("captchafy").setExecutor(new CaptchafyCommand());
try
{
configs = new Configuration();
configs.startup();
if (configs.isIncomplete())
{
Bukkit.getLogger().severe("[Captchafy] There is information missing in the config. Please make the appropriate changes. " +
"This is normal on the first run. Reload the server once you have made the correct edits.");
Captchafy.error = true;
Bukkit.getPluginManager().disablePlugin(Captchafy.plugin);
return;
}
}
catch (IOException e)
{
e.printStackTrace();
}
securityLevel = configs.config.getInt("security-level");
if (securityLevel > 3 || securityLevel < 1)
{
securityLevel = 2;
Bukkit.getLogger().severe("[Captchafy] The 'security-level' config field was not between 1 and 3. Setting security level to 2.");
}
enabled = configs.config.getBoolean("always-on");
server = HttpdServer.getServer();
listeners.setURLMessage();
Bukkit.getLogger().info("[Captchafy] Running in security level " + securityLevel + ".");
}
@Override
public void onDisable()
{
if (error)
{
return; //Prevents errors on the first startup.
}
try
{
configs.saveNames(true);
configs.saveConfig();
}
catch (IOException e)
{
e.printStackTrace();
}
server.shutdownNow();
configs.ipList.clear(); //TODO See if removing this line affects functionality.
}
}

View File

@ -1,119 +1,119 @@
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.capatchafy;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
public class CapatchafyCommand implements CommandExecutor
{
//Friendly - One time verification.
//Moderate - One time verification for each time the server starts.
//Strict - Needs verification each time you join/leave.
@Override
public boolean onCommand(CommandSender sender, Command cmd, String cL, String[] args)
{
//TODO Implement command permissions with TFM and bukkit permissions.
if (!sender.hasPermission("capatchafy.command"))
{
sender.sendMessage(ChatColor.RED + "You do not have permission to use this command.");
return false;
}
if (Capatchafy.configs.config.getBoolean("always-on"))
{
sender.sendMessage(ChatColor.RED + "The server owner has Capatchafy enabled at all times. You are not allowed to turn it off or change the security level.");
return false;
}
//TODO Fix arguments problem, it will throw errors if the parameters aren't filled out properly. Also, make it show usage when the security level arg is spelled wrong.
if (args.length < 1)
{
sender.sendMessage("Usage: /capatchafy <on:off:status> <friendly:moderate:strict>");
return false;
}
if (args[0].equalsIgnoreCase("on"))
{
Capatchafy.enabled = true;
Bukkit.broadcastMessage(ChatColor.DARK_RED + "Capatcha-based verification has been enabled.");
//TODO Add time based disabling of capatchafy. E.g. when admin that turns capatchafy on leaves, turn capatchafy off.
//If it does not match any of these, we just keep the security level as is.
//Remember, the security level only changes when we tell it to with this command.
Capatchafy.forced = true;
Capatchafy.listeners.numberOfAttacks = 0;
if (args.length < 2)
{
sender.sendMessage("Capatchafy will run in security level " + Capatchafy.securityLevel + ". It will not be auto-disabled.");
return true;
}
if (args[1].equalsIgnoreCase("friendly") || args[1].equalsIgnoreCase("1"))
{
Capatchafy.securityLevel = 1;
}
else if (args[1].equalsIgnoreCase("moderate") || args[1].equalsIgnoreCase("2"))
{
Capatchafy.securityLevel = 2;
}
else if (args[1].equalsIgnoreCase("strict") || args[1].equalsIgnoreCase("3"))
{
Capatchafy.securityLevel = 3;
Capatchafy.configs.ipList.clear();
}
else
{
sender.sendMessage("Usage: /capatchafy <on:off:status> <friendly:moderate:strict>");
return false;
}
sender.sendMessage("Capatchafy will run in security level " + Capatchafy.securityLevel + ". It will not be auto-disabled.");
return true;
}
else if (args[0].equalsIgnoreCase("off"))
{
Capatchafy.enabled = false;
Capatchafy.forced = false;
Capatchafy.listeners.numberOfAttacks = 0;
Bukkit.broadcastMessage(ChatColor.GREEN + "Capatcha-based verification has been disabled.");
if (args.length < 2)
return true;
if (args[1].equalsIgnoreCase("-f"))
{
Capatchafy.forced = true;
sender.sendMessage(ChatColor.YELLOW + "Capatchafy " + ChatColor.RED + "will not" + ChatColor.YELLOW + " automatically enable if the server detects an attack.");
return true;
}
}
else if (args[0].equalsIgnoreCase("status"))
{
sender.sendMessage(ChatColor.GRAY + "Capatchafy is enabled: " + ChatColor.YELLOW + Capatchafy.enabled);
sender.sendMessage(ChatColor.GRAY + "Capatchafy is set to run in mode: " + ChatColor.YELLOW + Capatchafy.securityLevel);
return true;
}
else
{
sender.sendMessage("Usage: /capatchafy <on:off:status> <friendly:moderate:strict>");
}
return false;
}
}
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.captchafy;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
public class CaptchafyCommand implements CommandExecutor
{
//Friendly - One time verification.
//Moderate - One time verification for each time the server starts.
//Strict - Needs verification each time you join/leave.
@Override
public boolean onCommand(CommandSender sender, Command cmd, String cL, String[] args)
{
//TODO Implement command permissions with TFM and bukkit permissions.
if (!sender.hasPermission("captchafy.command"))
{
sender.sendMessage(ChatColor.RED + "You do not have permission to use this command.");
return false;
}
if (Captchafy.configs.config.getBoolean("always-on"))
{
sender.sendMessage(ChatColor.RED + "The server owner has Captchafy enabled at all times. You are not allowed to turn it off or change the security level.");
return false;
}
//TODO Fix arguments problem, it will throw errors if the parameters aren't filled out properly. Also, make it show usage when the security level arg is spelled wrong.
if (args.length < 1)
{
sender.sendMessage("Usage: /captchafy <on:off:status> <friendly:moderate:strict>");
return false;
}
if (args[0].equalsIgnoreCase("on"))
{
Captchafy.enabled = true;
Bukkit.broadcastMessage(ChatColor.DARK_RED + "Captcha-based verification has been enabled.");
//TODO Add time based disabling of captchafy. E.g. when admin that turns captchafy on leaves, turn captchafy off.
//If it does not match any of these, we just keep the security level as is.
//Remember, the security level only changes when we tell it to with this command.
Captchafy.forced = true;
Captchafy.listeners.numberOfAttacks = 0;
if (args.length < 2)
{
sender.sendMessage("Captchafy will run in security level " + Captchafy.securityLevel + ". It will not be auto-disabled.");
return true;
}
if (args[1].equalsIgnoreCase("friendly") || args[1].equalsIgnoreCase("1"))
{
Captchafy.securityLevel = 1;
}
else if (args[1].equalsIgnoreCase("moderate") || args[1].equalsIgnoreCase("2"))
{
Captchafy.securityLevel = 2;
}
else if (args[1].equalsIgnoreCase("strict") || args[1].equalsIgnoreCase("3"))
{
Captchafy.securityLevel = 3;
Captchafy.configs.ipList.clear();
}
else
{
sender.sendMessage("Usage: /captchafy <on:off:status> <friendly:moderate:strict>");
return false;
}
sender.sendMessage("Captchafy will run in security level " + Captchafy.securityLevel + ". It will not be auto-disabled.");
return true;
}
else if (args[0].equalsIgnoreCase("off"))
{
Captchafy.enabled = false;
Captchafy.forced = false;
Captchafy.listeners.numberOfAttacks = 0;
Bukkit.broadcastMessage(ChatColor.GREEN + "Captcha-based verification has been disabled.");
if (args.length < 2)
return true;
if (args[1].equalsIgnoreCase("-f"))
{
Captchafy.forced = true;
sender.sendMessage(ChatColor.YELLOW + "Captchafy " + ChatColor.RED + "will not" + ChatColor.YELLOW + " automatically enable if the server detects an attack.");
return true;
}
}
else if (args[0].equalsIgnoreCase("status"))
{
sender.sendMessage(ChatColor.GRAY + "Captchafy is enabled: " + ChatColor.YELLOW + Captchafy.enabled);
sender.sendMessage(ChatColor.GRAY + "Captchafy is set to run in mode: " + ChatColor.YELLOW + Captchafy.securityLevel);
return true;
}
else
{
sender.sendMessage("Usage: /captchafy <on:off:status> <friendly:moderate:strict>");
}
return false;
}
}

View File

@ -1,161 +1,160 @@
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.capatchafy;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Configuration
{
//TODO Add time based authorization expiration.
FileConfiguration ips;
File ipsFile = new File(Capatchafy.plugin.getDataFolder(), "ips.yml");
FileConfiguration config;
File configFile = new File(Capatchafy.plugin.getDataFolder(), "config.yml");
public List<String> ipList = new ArrayList();
public List<String> alwaysAuthorizedList = new ArrayList();
public void startup() throws IOException
{
saveConfig();
saveNames(false);
loadConfigs();
}
public boolean isIncomplete()
{
return getHostname() == null || getPort() == null || getCapatchaSiteKey() == null || getCapatchaSecret() == null || config.get("always-on") == null || config.get("security-level") == null;
}
//TODO Cleanup. This actually generates the config, but saves the ips if true. Causes NPE if saved before loadConfig()
public void saveNames(boolean save) throws IOException
{
if (ipsFile == null)
{
ipsFile = new File(Capatchafy.plugin.getDataFolder(), "ips.yml");
}
if (!ipsFile.exists())
{
Capatchafy.plugin.saveResource("ips.yml", false);
}
if (save)
{
ips.set("authorized-ips", alwaysAuthorizedList);
ips.save(ipsFile);
}
}
//TODO Cleanup. Just generates config, not saves it.
public void saveConfig() throws IOException
{
if (configFile == null)
{
configFile = new File(Capatchafy.plugin.getDataFolder(), "config.yml");
}
if (!configFile.exists())
{
Capatchafy.plugin.saveResource("config.yml", false);
}
}
public void loadConfigs() throws IOException
{
config = YamlConfiguration.loadConfiguration(configFile);
ips = YamlConfiguration.loadConfiguration(ipsFile);
alwaysAuthorizedList = ips.getStringList("authorized-ips");
}
public void setAuthorized(String ip, boolean authorize)
{
if (!authorize)
{
ipList.remove(ip);
return;
//We dont remove always authorized ips, because they were added while in the friendly mode, so they should still be added to the ips.yml.
}
switch (Capatchafy.securityLevel)
{
case 1:
{
if (!ipList.contains(ip)) ipList.add(ip);
alwaysAuthorizedList.add(ip);
}
case 2:
{
if (!ipList.contains(ip)) ipList.add(ip);
}
case 3:
{
if (!ipList.contains(ip)) ipList.add(ip);
}
}
}
public boolean isAuthorized(String ip)
{
if (config.getStringList("whitelisted-ips").contains(ip))
{
return true;
}
switch (Capatchafy.securityLevel)
{
case 1:
{
return alwaysAuthorizedList.contains(ip) || config.getStringList("authorized-ips").contains(ip);
}
case 2:
{
return ipList.contains(ip);
}
case 3:
{
return ipList.contains(ip);
}
}
return false;
}
public String getHostname()
{
return config.getString("hostname");
}
public String getBindingIP()
{
return config.getString("binding-ip");
}
public String getPort()
{
return config.getString("port");
}
public String getCapatchaSiteKey()
{
return config.getString("recapatcha-key");
}
public String getCapatchaSecret()
{
return config.getString("recapatcha-secret");
}
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.captchafy;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class Configuration
{
//TODO Add time based authorization expiration.
FileConfiguration ips;
File ipsFile = new File(Captchafy.plugin.getDataFolder(), "ips.yml");
FileConfiguration config;
File configFile = new File(Captchafy.plugin.getDataFolder(), "config.yml");
public List<String> ipList = new ArrayList();
public List<String> alwaysAuthorizedList = new ArrayList();
public void startup() throws IOException
{
saveConfig();
saveNames(false);
loadConfigs();
}
public boolean isIncomplete()
{
return getHostname() == null || getPort() == null || getCaptchaSiteKey() == null || getCaptchaSecret() == null || config.get("always-on") == null || config.get("security-level") == null;
}
//TODO Cleanup. This actually generates the config, but saves the ips if true. Causes NPE if saved before loadConfig()
public void saveNames(boolean save) throws IOException
{
if (ipsFile == null)
{
ipsFile = new File(Captchafy.plugin.getDataFolder(), "ips.yml");
}
if (!ipsFile.exists())
{
Captchafy.plugin.saveResource("ips.yml", false);
}
if (save)
{
ips.set("authorized-ips", alwaysAuthorizedList);
ips.save(ipsFile);
}
}
//TODO Cleanup. Just generates config, not saves it.
public void saveConfig() throws IOException
{
if (configFile == null)
{
configFile = new File(Captchafy.plugin.getDataFolder(), "config.yml");
}
if (!configFile.exists())
{
Captchafy.plugin.saveResource("config.yml", false);
}
}
public void loadConfigs() throws IOException
{
config = YamlConfiguration.loadConfiguration(configFile);
ips = YamlConfiguration.loadConfiguration(ipsFile);
alwaysAuthorizedList = ips.getStringList("authorized-ips");
}
public void setAuthorized(String ip, boolean authorize)
{
if (!authorize)
{
ipList.remove(ip);
return;
//We dont remove always authorized ips, because they were added while in the friendly mode, so they should still be added to the ips.yml.
}
switch (Captchafy.securityLevel)
{
case 1:
{
if (!ipList.contains(ip)) ipList.add(ip);
alwaysAuthorizedList.add(ip);
}
case 2:
{
if (!ipList.contains(ip)) ipList.add(ip);
}
case 3:
{
if (!ipList.contains(ip)) ipList.add(ip);
}
}
}
public boolean isAuthorized(String ip)
{
if (config.getStringList("whitelisted-ips").contains(ip))
{
return true;
}
switch (Captchafy.securityLevel)
{
case 1:
{
return alwaysAuthorizedList.contains(ip) || config.getStringList("authorized-ips").contains(ip);
}
case 2:
{
return ipList.contains(ip);
}
case 3:
{
return ipList.contains(ip);
}
}
return false;
}
public String getHostname()
{
return config.getString("hostname");
}
public String getBindingIP()
{
return config.getString("binding-ip");
}
public String getPort()
{
return config.getString("port");
}
public String getCaptchaSiteKey()
{
return config.getString("recaptcha-key");
}
public String getCaptchaSecret()
{
return config.getString("recaptcha-secret");
}
}

View File

@ -1,150 +1,150 @@
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.capatchafy;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import java.util.Date;
import org.bukkit.ChatColor;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.scheduler.BukkitRunnable;
public class Listeners implements Listener
{
//Auto-enable Settings
public int points;
public Date lastLogin;
public int numberOfAttacks; //This is the number of attacks since admin intervention, not necessarily the number of attacks since the server has been online.
public long throttleTime; //The higher, the more often players will be counted as possible spammers. Required time between each login to not be considered an attack.
public int throttleLogins; //The lower, the quicker the capatchas will auto-enable. Aka max points before capatchafy is enabled.
public long removeAllPointsTime = 7L; //Remove all points after x seconds. Default: 7
public int maxAttacks = 3; //Set to 0 to disable this function. Default: 3
public long startupThrottleTime = 1L; //The throttle time on startup. Default: 1
public int startupThrottleLogins = 20; //The throttle logins on startup. Default: 20
public long defaultThrottleTime = 3L; //After 30 seconds, the server defaults back to this. Default: 3
public int defaultThrottleLogins = 8; //Default: 8
public static String url;
//TODO If IP matches IP in TFM, dont force admins to verify.
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerLogin(PlayerLoginEvent event)
{
if (!Capatchafy.forced && !Capatchafy.configs.config.getBoolean("always-on") && !Capatchafy.enabled)
{
throttleConnections();
}
if (!Capatchafy.enabled) return;
String ip = event.getAddress().toString().replaceAll("/", "");
if (!Capatchafy.configs.isAuthorized(ip))
{
if (url == null)
{
setURLMessage();
}
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, ChatColor.RED + "" + ChatColor.BOLD + "Yikes, we're under attack! Please solve the capatcha.\n" +
ChatColor.WHITE + "Please go to " + ChatColor.GOLD + url + ChatColor.WHITE + " in your web browser and solve the capatcha.\n" +
"Once solved successfully, you will be able to join.");
return;
}
if (Capatchafy.securityLevel == 3)
{
Capatchafy.configs.setAuthorized(ip, false);
}
}
public void throttleConnections()
{
if (lastLogin == null)
{
lastLogin = new Date();
return;
}
Date currentTime = new Date();
long diffInSeconds = (currentTime.getTime() - lastLogin.getTime()) / 1000 % 60;
if (diffInSeconds <= throttleTime && points != throttleLogins) //points != throttleLogins works because it adds a point when the points is not the ammount needed to throttle.
{
points++;
}
if (diffInSeconds >= removeAllPointsTime)
{
points = 0;
}
if (points == throttleLogins && !Capatchafy.enabled)
{
Bukkit.broadcastMessage(ChatColor.DARK_RED + "Capatcha-based verification has been enabled.");
Capatchafy.enabled = true;
numberOfAttacks++;
points = 0;
new BukkitRunnable()
{
@Override
public void run()
{
if (!Capatchafy.forced && Capatchafy.enabled)
{
Bukkit.broadcastMessage(ChatColor.GREEN + "Capatcha-based verification has been disabled.");
Capatchafy.enabled = false;
}
}
}.runTaskLater(Capatchafy.plugin, 5 * 60 * 20); //Default 5 * 60 * 20
}
if (numberOfAttacks >= maxAttacks && maxAttacks != 0)
{
Capatchafy.enabled = true;
Capatchafy.forced = true;
lastLogin = currentTime;
Bukkit.broadcastMessage(ChatColor.DARK_RED + "Capatchafy will not auto-disable.");
return;
}
lastLogin = currentTime;
}
public void setURLMessage()
{
if (Capatchafy.configs.getPort().equals("80"))
{
url = Capatchafy.configs.getHostname();
return;
}
url = Capatchafy.configs.getHostname() + ":" + Capatchafy.configs.getPort();
}
public void setThrottleSettings()
{
this.throttleTime = startupThrottleTime;
this.throttleLogins = startupThrottleLogins;
new BukkitRunnable()
{
@Override
public void run()
{
throttleTime = defaultThrottleTime;
throttleLogins = defaultThrottleLogins;
}
}.runTaskLater(Capatchafy.plugin, 1200);
}
}
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.captchafy;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import java.util.Date;
import org.bukkit.ChatColor;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.scheduler.BukkitRunnable;
public class Listeners implements Listener
{
//Auto-enable Settings
public int points;
public Date lastLogin;
public int numberOfAttacks; //This is the number of attacks since admin intervention, not necessarily the number of attacks since the server has been online.
public long throttleTime; //The higher, the more often players will be counted as possible spammers. Required time between each login to not be considered an attack.
public int throttleLogins; //The lower, the quicker the captchas will auto-enable. Aka max points before captchafy is enabled.
public long removeAllPointsTime = 7L; //Remove all points after x seconds. Default: 7
public int maxAttacks = 3; //Set to 0 to disable this function. Default: 3
public long startupThrottleTime = 1L; //The throttle time on startup. Default: 1
public int startupThrottleLogins = 20; //The throttle logins on startup. Default: 20
public long defaultThrottleTime = 3L; //After 30 seconds, the server defaults back to this. Default: 3
public int defaultThrottleLogins = 8; //Default: 8
public static String url;
//TODO If IP matches IP in TFM, dont force admins to verify.
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerLogin(PlayerLoginEvent event)
{
if (!Captchafy.forced && !Captchafy.configs.config.getBoolean("always-on") && !Captchafy.enabled)
{
throttleConnections();
}
if (!Captchafy.enabled) return;
String ip = event.getAddress().toString().replaceAll("/", "");
if (!Captchafy.configs.isAuthorized(ip))
{
if (url == null)
{
setURLMessage();
}
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, ChatColor.RED + "" + ChatColor.BOLD + "Yikes, we're under attack! Please solve the captcha.\n" +
ChatColor.WHITE + "Please go to " + ChatColor.GOLD + url + ChatColor.WHITE + " in your web browser and solve the captcha.\n" +
"Once solved successfully, you will be able to join.");
return;
}
if (Captchafy.securityLevel == 3)
{
Captchafy.configs.setAuthorized(ip, false);
}
}
public void throttleConnections()
{
if (lastLogin == null)
{
lastLogin = new Date();
return;
}
Date currentTime = new Date();
long diffInSeconds = (currentTime.getTime() - lastLogin.getTime()) / 1000 % 60;
if (diffInSeconds <= throttleTime && points != throttleLogins) //points != throttleLogins works because it adds a point when the points is not the ammount needed to throttle.
{
points++;
}
if (diffInSeconds >= removeAllPointsTime)
{
points = 0;
}
if (points == throttleLogins && !Captchafy.enabled)
{
Bukkit.broadcastMessage(ChatColor.DARK_RED + "Captcha-based verification has been enabled.");
Captchafy.enabled = true;
numberOfAttacks++;
points = 0;
new BukkitRunnable()
{
@Override
public void run()
{
if (!Captchafy.forced && Captchafy.enabled)
{
Bukkit.broadcastMessage(ChatColor.GREEN + "Captcha-based verification has been disabled.");
Captchafy.enabled = false;
}
}
}.runTaskLater(Captchafy.plugin, 5 * 60 * 20); //Default 5 * 60 * 20
}
if (numberOfAttacks >= maxAttacks && maxAttacks != 0)
{
Captchafy.enabled = true;
Captchafy.forced = true;
lastLogin = currentTime;
Bukkit.broadcastMessage(ChatColor.DARK_RED + "Captchafy will not auto-disable.");
return;
}
lastLogin = currentTime;
}
public void setURLMessage()
{
if (Captchafy.configs.getPort().equals("80"))
{
url = Captchafy.configs.getHostname();
return;
}
url = Captchafy.configs.getHostname() + ":" + Captchafy.configs.getPort();
}
public void setThrottleSettings()
{
this.throttleTime = startupThrottleTime;
this.throttleLogins = startupThrottleLogins;
new BukkitRunnable()
{
@Override
public void run()
{
throttleTime = defaultThrottleTime;
throttleLogins = defaultThrottleLogins;
}
}.runTaskLater(Captchafy.plugin, 1200);
}
}

View File

@ -1,114 +1,114 @@
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.capatchafy.httpd;
import me.hockey.capatchafy.Capatchafy;
import org.bukkit.Bukkit;
import org.glassfish.grizzly.http.server.Request;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
@Path("/")
public class CapatchaPage
{
@GET
@Produces(MediaType.TEXT_HTML)
public String urlAccessed(@Context Request req)
{
if (Capatchafy.configs.isAuthorized(req.getRemoteAddr()) || !Capatchafy.enabled)
{
return "You are already authorized.";
}
return "<head>" +
"<script src='https://www.google.com/recaptcha/api.js'></script></head>" +
"<script>function callback(){document.getElementById(\"form\").submit();}</script>"+
"<form id=\"form\"method=\"post\">" +
"<div class=\"g-recaptcha\" data-callback=\"callback\" data-sitekey=\"" + Capatchafy.configs.getCapatchaSiteKey() + "\"></div>" +
"</form>";
}
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void handlePost(@FormParam("g-recaptcha-response") String content, @Context Request req)
{
try
{
//Bukkit.getLogger().info("A capatcha has been recieved from " + req.getRemoteAddr());
if (validateCaptcha(Capatchafy.configs.getCapatchaSecret(), content, req.getRemoteAddr()))
{
//Bukkit.getLogger().info("Capatcha from " + req.getRemoteAddr() + " is valid.");
Capatchafy.configs.setAuthorized(req.getRemoteAddr(), true);
}
}
catch (Exception e)
{
System.out.print(e.getLocalizedMessage());
}
}
public boolean validateCaptcha(String secret, String response, String remoteip)
{
JsonObject jsonObject = null;
URLConnection connection = null;
InputStream is = null;
String charset = java.nio.charset.StandardCharsets.UTF_8.name();
String url = "https://www.google.com/recaptcha/api/siteverify";
try
{
String query = String.format("secret=%s&response=%s&remoteip=%s",
URLEncoder.encode(secret, charset),
URLEncoder.encode(response, charset),
URLEncoder.encode(remoteip, charset));
connection = new URL(url + "?" + query).openConnection();
is = connection.getInputStream();
JsonReader rdr = Json.createReader(is);
jsonObject = rdr.readObject();
}
catch (IOException ex)
{
Bukkit.broadcastMessage(ex.getStackTrace().toString());
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException e)
{
System.out.print(e.getLocalizedMessage());
}
}
}
return jsonObject.getBoolean("success");
}
}
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.captchafy.httpd;
import me.hockey.captchafy.Captchafy;
import org.bukkit.Bukkit;
import org.glassfish.grizzly.http.server.Request;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
@Path("/")
public class CaptchaPage
{
@GET
@Produces(MediaType.TEXT_HTML)
public String urlAccessed(@Context Request req)
{
if (Captchafy.configs.isAuthorized(req.getRemoteAddr()) || !Captchafy.enabled)
{
return "You are already authorized.";
}
return "<head>" +
"<script src='https://www.google.com/recaptcha/api.js'></script></head>" +
"<script>function callback(){document.getElementById(\"form\").submit();}</script>"+
"<form id=\"form\"method=\"post\">" +
"<div class=\"g-recaptcha\" data-callback=\"callback\" data-sitekey=\"" + Captchafy.configs.getCaptchaSiteKey() + "\"></div>" +
"</form>";
}
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void handlePost(@FormParam("g-recaptcha-response") String content, @Context Request req)
{
try
{
//Bukkit.getLogger().info("A captcha has been recieved from " + req.getRemoteAddr());
if (validateCaptcha(Captchafy.configs.getCaptchaSecret(), content, req.getRemoteAddr()))
{
//Bukkit.getLogger().info("Captcha from " + req.getRemoteAddr() + " is valid.");
Captchafy.configs.setAuthorized(req.getRemoteAddr(), true);
}
}
catch (Exception e)
{
System.out.print(e.getLocalizedMessage());
}
}
public boolean validateCaptcha(String secret, String response, String remoteip)
{
JsonObject jsonObject = null;
URLConnection connection = null;
InputStream is = null;
String charset = java.nio.charset.StandardCharsets.UTF_8.name();
String url = "https://www.google.com/recaptcha/api/siteverify";
try
{
String query = String.format("secret=%s&response=%s&remoteip=%s",
URLEncoder.encode(secret, charset),
URLEncoder.encode(response, charset),
URLEncoder.encode(remoteip, charset));
connection = new URL(url + "?" + query).openConnection();
is = connection.getInputStream();
JsonReader rdr = Json.createReader(is);
jsonObject = rdr.readObject();
}
catch (IOException ex)
{
Bukkit.broadcastMessage(ex.getStackTrace().toString());
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException e)
{
System.out.print(e.getLocalizedMessage());
}
}
}
return jsonObject.getBoolean("success");
}
}

View File

@ -1,39 +1,39 @@
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.capatchafy.httpd;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;
import me.hockey.capatchafy.Capatchafy;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
public class HttpdServer
{
public static final String BASE_URI = "http://" + (Capatchafy.configs.getBindingIP().isEmpty() ? Capatchafy.configs.getHostname() : Capatchafy.configs.getBindingIP()) + ":" + Capatchafy.configs.getPort() + "/";
public static HttpServer getServer()
{
final ResourceConfig rc = new ResourceConfig().packages("me.hockey.capatchafy.httpd");
final Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(CapatchaPage.class);
rc.registerClasses(classes);
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
}
/*
Copyright (C) 2017 James Depp
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.captchafy.httpd;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;
import me.hockey.captchafy.Captchafy;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
public class HttpdServer
{
public static final String BASE_URI = "http://" + (Captchafy.configs.getBindingIP().isEmpty() ? Captchafy.configs.getHostname() : Captchafy.configs.getBindingIP()) + ":" + Captchafy.configs.getPort() + "/";
public static HttpServer getServer()
{
final ResourceConfig rc = new ResourceConfig().packages("me.hockey.captchafy.httpd");
final Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(CaptchaPage.class);
rc.registerClasses(classes);
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
}

View File

@ -1,11 +1,11 @@
#This is the main configuration file for Capatchafy 1.0, a plugin by James Depp.
#This is the main configuration file for Captchafy 1.0, a plugin by James Depp.
#Authorized-IPs are located in ips.yml. If you want to wipe them, delete ips.yml, WHILE THE SERVER IS STOPPED. It will reverse your actions if the server is alive.
#If you would like Capatchafy to be enabled all the time, you can specify that here.
#If you would like Captchafy to be enabled all the time, you can specify that here.
always-on: false
#This is the default security level. This value should be an integer between 1 and 3.
#Any security level can be selected with the /capatchafy command.
#Any security level can be selected with the /captchafy command.
#1 - Friendly. One time verification, ips will be stored in config.
#2 - Moderate (Recommended). You must verify each time the server restarts/reloads.
#3 - Strict. You must verify each time you join.
@ -14,23 +14,23 @@ security-level: 2
# IP to bind the httpd to, leave blank to use hostname
binding-ip: ''
#Hostname - The ip that you want Capatchafy to listen on goes here.
#You don't HAVE to change this, but leaving it will cause problems when a player tries to find the link to the capatcha.
#Hostname - The ip that you want Captchafy to listen on goes here.
#You don't HAVE to change this, but leaving it will cause problems when a player tries to find the link to the captcha.
hostname: 127.0.0.1
#Port - The port that you want Capatchafy to run on goes here.
#Port - The port that you want Captchafy to run on goes here.
#Use port 80 if you don't want your players to have to type a port in the address bar. On some machines, port 80 may already be in use.
#If you're not sure about which port to use, just pick a random one. If you're running a VPS, be sure to open the port in the firewall.
port: 8080
#Whitelisted IPs - IPs that will never have to go through the capatcha verification process.
#Whitelisted IPs - IPs that will never have to go through the captcha verification process.
whitelisted-ips:
- 127.0.0.1
#This is the tricky part. You will need to obtain api keys for reCapatcha.
#To obtain a reCapatcha key, click on https://www.google.com/recaptcha/intro/index.html and click "Get Started."
#Enter in a name for your 'site', it can be anything. Then, give the hostname you put here as the url to your capatcha.
#Your site key goes in the 'recapatcha-key' section, your secret key (which you should never give out) goes in the 'recapatcha-secret' section.
recapatcha-key:
recapatcha-secret:
#To obtain a recaptcha key, click on https://www.google.com/recaptcha/intro/index.html and click "Get Started."
#Enter in a name for your 'site', it can be anything. Then, give the hostname you put here as the url to your captcha.
#Your site key goes in the 'recaptcha-key' section, your secret key (which you should never give out) goes in the 'recaptcha-secret' section.
recaptcha-key:
recaptcha-secret:

View File

@ -1,10 +1,10 @@
name: Capatchafy
name: Captchafy
version: 1.1.0-TF
main: me.hockey.capatchafy.Capatchafy
main: me.hockey.captchafy.Captchafy
commands:
capatchafy:
captchafy:
capatchafy.command:
description: Allow a player to use the capatchafy command.
captchafy.command:
description: Allow a player to use the captchafy command.
default: op