mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-11-28 13:15:30 +01:00
Add support for 'use-player-login-ip', 'require-player-login-ip' - map player login IP addresses to web chat addresses
This commit is contained in:
parent
09fbf312ac
commit
e009aefb18
@ -6,11 +6,13 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -86,6 +88,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
private int config_hashcode; /* Used to signal need to reload web configuration (world changes, config update, etc) */
|
||||
private int fullrenderplayerlimit; /* Number of online players that will cause fullrender processing to pause */
|
||||
private boolean didfullpause;
|
||||
private Map<String, LinkedList<String>> ids_by_ip = new HashMap<String, LinkedList<String>>();
|
||||
private boolean persist_ids_by_ip = false;
|
||||
|
||||
public enum CompassMode {
|
||||
PRE19, /* Default for 1.8 and earlier (east is Z+) */
|
||||
@ -278,6 +282,10 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
compassmode = CompassMode.PRE19;
|
||||
/* Load full render processing player limit */
|
||||
fullrenderplayerlimit = configuration.getInteger("fullrenderplayerlimit", 0);
|
||||
/* If we're persisting ids-by-ip, load it */
|
||||
persist_ids_by_ip = configuration.getBoolean("persist-ids-by-ip", true);
|
||||
if(persist_ids_by_ip)
|
||||
loadIDsByIP();
|
||||
|
||||
loadDebuggers();
|
||||
|
||||
@ -290,6 +298,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
playerList.load();
|
||||
PlayerListener pl = new PlayerListener() {
|
||||
public void onPlayerJoin(PlayerJoinEvent evt) {
|
||||
Player p = evt.getPlayer();
|
||||
playerList.updateOnlinePlayers(null);
|
||||
if(fullrenderplayerlimit > 0) {
|
||||
if((getServer().getOnlinePlayers().length+1) >= fullrenderplayerlimit) {
|
||||
@ -300,6 +309,23 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Add player info to IP-to-ID table */
|
||||
InetSocketAddress addr = p.getAddress();
|
||||
if(addr != null) {
|
||||
String ip = addr.getAddress().getHostAddress();
|
||||
LinkedList<String> ids = ids_by_ip.get(ip);
|
||||
if(ids == null) {
|
||||
ids = new LinkedList<String>();
|
||||
ids_by_ip.put(ip, ids);
|
||||
}
|
||||
String pid = p.getName();
|
||||
/* See if not first in list */
|
||||
int idx = ids.indexOf(pid);
|
||||
if(idx > 0) {
|
||||
ids.remove(idx);
|
||||
}
|
||||
ids.addFirst(pid); /* Put us first on list */
|
||||
}
|
||||
}
|
||||
public void onPlayerQuit(PlayerQuitEvent evt) {
|
||||
playerList.updateOnlinePlayers(evt.getPlayer());
|
||||
@ -412,6 +438,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if(persist_ids_by_ip)
|
||||
saveIDsByIP();
|
||||
if (componentManager != null) {
|
||||
int componentCount = componentManager.components.size();
|
||||
for(Component component : componentManager.components) {
|
||||
@ -767,7 +795,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
"resetstats",
|
||||
"sendtoweb",
|
||||
"pause",
|
||||
"purgequeue" }));
|
||||
"purgequeue",
|
||||
"ids-for-ip",
|
||||
"ips-for-id" }));
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
|
||||
@ -954,6 +984,31 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
msg += args[i] + " ";
|
||||
}
|
||||
this.sendBroadcastToWeb("dynmap", msg);
|
||||
} else if(c.equals("ids-for-ip") && checkPlayerPermission(sender, "ids-for-ip")) {
|
||||
if(args.length > 1) {
|
||||
List<String> ids = getIDsForIP(args[1]);
|
||||
sender.sendMessage("IDs logged in from address " + args[1] + " (most recent to least):");
|
||||
if(ids != null) {
|
||||
for(String id : ids)
|
||||
sender.sendMessage(" " + id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sender.sendMessage("IP address required as parameter");
|
||||
}
|
||||
} else if(c.equals("ips-for-id") && checkPlayerPermission(sender, "ips-for-id")) {
|
||||
if(args.length > 1) {
|
||||
sender.sendMessage("IP addresses logged for player " + args[1] + ":");
|
||||
for(String ip: ids_by_ip.keySet()) {
|
||||
LinkedList<String> ids = ids_by_ip.get(ip);
|
||||
if((ids != null) && ids.contains(args[1])) {
|
||||
sender.sendMessage(" " + ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
sender.sendMessage("Player ID required as parameter");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1536,4 +1591,56 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
|
||||
mapManager.pushUpdate(new Client.PlayerQuitMessage(player.getDisplayName(), player.getName()));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get list of IDs seen on give IP (most recent to least recent)
|
||||
*/
|
||||
public List<String> getIDsForIP(InetAddress addr) {
|
||||
return getIDsForIP(addr.getHostAddress());
|
||||
}
|
||||
/**
|
||||
* Get list of IDs seen on give IP (most recent to least recent)
|
||||
*/
|
||||
public List<String> getIDsForIP(String ip) {
|
||||
LinkedList<String> ids = ids_by_ip.get(ip);
|
||||
if(ids != null)
|
||||
return new ArrayList<String>(ids);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void loadIDsByIP() {
|
||||
File f = new File(getDataFolder(), "ids-by-ip.txt");
|
||||
if(f.exists() == false)
|
||||
return;
|
||||
YamlConfiguration fc = new YamlConfiguration();
|
||||
try {
|
||||
fc.load(new File(getDataFolder(), "ids-by-ip.txt"));
|
||||
ids_by_ip.clear();
|
||||
Map<String,Object> v = fc.getValues(false);
|
||||
for(String k : v.keySet()) {
|
||||
List<String> ids = fc.getStringList(k);
|
||||
if(ids != null) {
|
||||
k = k.replace("_", ".");
|
||||
ids_by_ip.put(k, new LinkedList<String>(ids));
|
||||
}
|
||||
}
|
||||
} catch (Exception iox) {
|
||||
Log.severe("Error loading " + f.getPath() + " - " + iox.getMessage());
|
||||
}
|
||||
}
|
||||
private void saveIDsByIP() {
|
||||
File f = new File(getDataFolder(), "ids-by-ip.txt");
|
||||
YamlConfiguration fc = new YamlConfiguration();
|
||||
for(String k : ids_by_ip.keySet()) {
|
||||
List<String> v = ids_by_ip.get(k);
|
||||
if(v != null) {
|
||||
k = k.replace(".", "_");
|
||||
fc.set(k, v);
|
||||
}
|
||||
}
|
||||
try {
|
||||
fc.save(f);
|
||||
} catch (Exception x) {
|
||||
Log.severe("Error saving " + f.getPath() + " - " + x.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,13 @@ import static org.dynmap.JSONUtils.*;
|
||||
|
||||
public class InternalClientUpdateComponent extends ClientUpdateComponent {
|
||||
|
||||
public InternalClientUpdateComponent(DynmapPlugin plugin, final ConfigurationNode configuration) {
|
||||
public InternalClientUpdateComponent(final DynmapPlugin plugin, final ConfigurationNode configuration) {
|
||||
super(plugin, configuration);
|
||||
final Boolean allowwebchat = configuration.getBoolean("allowwebchat", false);
|
||||
final Boolean hidewebchatip = configuration.getBoolean("hidewebchatip", false);
|
||||
final Boolean trust_client_name = configuration.getBoolean("trustclientname", false);
|
||||
final boolean allowwebchat = configuration.getBoolean("allowwebchat", false);
|
||||
final boolean hidewebchatip = configuration.getBoolean("hidewebchatip", false);
|
||||
final boolean trust_client_name = configuration.getBoolean("trustclientname", false);
|
||||
final boolean useplayerloginip = configuration.getBoolean("use-player-login-ip", true);
|
||||
final boolean requireplayerloginip = configuration.getBoolean("require-player-login-ip", false);
|
||||
final float webchatInterval = configuration.getFloat("webchat-interval", 1);
|
||||
final String spammessage = plugin.configuration.getString("spammessage", "You may only chat once every %interval% seconds.");
|
||||
|
||||
@ -31,7 +33,10 @@ public class InternalClientUpdateComponent extends ClientUpdateComponent {
|
||||
maximumMessageInterval = (int)(webchatInterval * 1000);
|
||||
spamMessage = "\""+spammessage+"\"";
|
||||
hideip = hidewebchatip;
|
||||
this.plug_in = plugin;
|
||||
this.trustclientname = trust_client_name;
|
||||
this.use_player_login_ip = useplayerloginip;
|
||||
this.require_player_login_ip = requireplayerloginip;
|
||||
onMessageReceived.addListener(new Listener<SendMessageHandler.Message>() {
|
||||
@Override
|
||||
public void triggered(Message t) {
|
||||
|
@ -9,6 +9,7 @@ import java.io.Reader;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
@ -26,7 +27,10 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
protected long currentTimestamp = 0;
|
||||
protected long lastTimestamp = 0;
|
||||
protected JSONParser parser = new JSONParser();
|
||||
private Boolean hidewebchatip;
|
||||
private boolean hidewebchatip;
|
||||
private boolean useplayerloginip;
|
||||
private boolean requireplayerloginip;
|
||||
private boolean trust_client_name;
|
||||
|
||||
private HashMap<String,String> useralias = new HashMap<String,String>();
|
||||
private int aliasindex = 1;
|
||||
@ -38,6 +42,10 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
final boolean allowwebchat = configuration.getBoolean("allowwebchat", false);
|
||||
jsonInterval = (long)(configuration.getFloat("writeinterval", 1) * 1000);
|
||||
hidewebchatip = configuration.getBoolean("hidewebchatip", false);
|
||||
useplayerloginip = configuration.getBoolean("use-player-login-ip", true);
|
||||
requireplayerloginip = configuration.getBoolean("require-player-login-ip", false);
|
||||
trust_client_name = configuration.getBoolean("trustclientname", false);
|
||||
|
||||
MapManager.scheduleDelayedJob(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -211,7 +219,24 @@ public class JsonFileClientUpdateComponent extends ClientUpdateComponent {
|
||||
if(ts.equals("null")) ts = "0";
|
||||
if (Long.parseLong(ts) >= (lastTimestamp)) {
|
||||
String name = String.valueOf(o.get("name"));
|
||||
if(hidewebchatip) {
|
||||
String ip = String.valueOf(o.get("ip"));
|
||||
boolean isip = true;
|
||||
if((!trust_client_name) || (name == null) || (name.equals(""))) {
|
||||
if(ip != null)
|
||||
name = ip;
|
||||
}
|
||||
if(useplayerloginip) { /* Try to match using IPs of player logins */
|
||||
List<String> ids = plugin.getIDsForIP(name);
|
||||
if(ids != null) {
|
||||
name = ids.get(0);
|
||||
isip = false;
|
||||
}
|
||||
else if(requireplayerloginip) {
|
||||
Log.info("Ignore message from '" + name + "' - no matching player login recorded");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(hidewebchatip && isip) {
|
||||
String n = useralias.get(name);
|
||||
if(n == null) { /* Make ID */
|
||||
n = String.format("web-%03d", aliasindex);
|
||||
|
@ -4,9 +4,12 @@ import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.dynmap.DynmapPlugin;
|
||||
import org.dynmap.Event;
|
||||
import org.dynmap.Log;
|
||||
import org.dynmap.web.HttpField;
|
||||
import org.dynmap.web.HttpHandler;
|
||||
import org.dynmap.web.HttpMethod;
|
||||
@ -25,6 +28,9 @@ public class SendMessageHandler implements HttpHandler {
|
||||
public int maximumMessageInterval = 1000;
|
||||
public boolean hideip = false;
|
||||
public boolean trustclientname = false;
|
||||
public boolean use_player_login_ip = false;
|
||||
public boolean require_player_login_ip = false;
|
||||
public DynmapPlugin plug_in;
|
||||
public String spamMessage = "\"You may only chat once every %interval% seconds.\"";
|
||||
private HashMap<String, WebUser> disallowedUsers = new HashMap<String, WebUser>();
|
||||
private LinkedList<WebUser> disallowedUserQueue = new LinkedList<WebUser>();
|
||||
@ -45,10 +51,12 @@ public class SendMessageHandler implements HttpHandler {
|
||||
JSONObject o = (JSONObject)parser.parse(reader);
|
||||
final Message message = new Message();
|
||||
|
||||
message.name = "";
|
||||
if(trustclientname) {
|
||||
message.name = String.valueOf(o.get("name"));
|
||||
}
|
||||
else {
|
||||
boolean isip = true;
|
||||
if((message.name == null) || message.name.equals("")) {
|
||||
/* If proxied client address, get original */
|
||||
if(request.fields.containsKey("X-Forwarded-For"))
|
||||
message.name = request.fields.get("X-Forwarded-For");
|
||||
@ -58,7 +66,18 @@ public class SendMessageHandler implements HttpHandler {
|
||||
else
|
||||
message.name = request.rmtaddr.getAddress().getHostAddress();
|
||||
}
|
||||
if(hideip) { /* If hiding IP, find or assign alias */
|
||||
if(use_player_login_ip) {
|
||||
List<String> ids = plug_in.getIDsForIP(message.name);
|
||||
if(ids != null) {
|
||||
message.name = ids.get(0);
|
||||
isip = false;
|
||||
}
|
||||
else if(require_player_login_ip) {
|
||||
Log.info("Ignore message from '" + message.name + "' - no matching player login recorded");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(hideip && isip) { /* If hiding IP, find or assign alias */
|
||||
synchronized(disallowedUsersLock) {
|
||||
String n = useralias.get(message.name);
|
||||
if(n == null) { /* Make ID */
|
||||
|
@ -27,6 +27,10 @@ components:
|
||||
hidewebchatip: false
|
||||
trustclientname: false
|
||||
includehiddenplayers: false
|
||||
# (optional) if true, player login IDs will be used for web chat when their IPs match
|
||||
use-player-login-ip: true
|
||||
# (optional) if use-player-login-ip is true, setting this to true will cause chat messages not matching a known player IP to be ignored
|
||||
require-player-login-ip: false
|
||||
# # Optional - make players hidden when they are inside/underground/in shadows (#=light level: 0=full shadow,15=sky)
|
||||
# hideifshadow: 4
|
||||
# # Optional - make player hidden when they are under cover (#=sky light level,0=underground,15=open to sky)
|
||||
@ -39,8 +43,10 @@ components:
|
||||
# webchat-interval: 5
|
||||
# hidewebchatip: false
|
||||
# includehiddenplayers: false
|
||||
# hideifshadow: 4
|
||||
# hideifundercover: 14
|
||||
# use-player-login-ip: false
|
||||
# require-player-login-ip: false
|
||||
# hideifshadow: 0
|
||||
# hideifundercover: 0
|
||||
|
||||
- class: org.dynmap.SimpleWebChatComponent
|
||||
allowchat: true
|
||||
@ -270,6 +276,9 @@ defaultmap: flat
|
||||
# Option to enable workaround for incorrectly encoded unicode in Cyrillic MC/Bukkit (not good for other code pages)
|
||||
cyrillic-support: false
|
||||
|
||||
# If true, make persistent record of IP addresses used by player logins, to support web IP to player matching
|
||||
persist-ids-by-ip: true
|
||||
|
||||
# NOTE: the 'templates' section is now found in the 'templates' directory
|
||||
# Templates CAN still be defined in configuration.txt, as before 0.20
|
||||
templates:
|
||||
|
@ -30,6 +30,7 @@ commands:
|
||||
/<command> purgequeue - Set tile update queue to empty
|
||||
/<command> pause - Show render pause state
|
||||
/<command> pause <all|none|full|update> - Set render pause state
|
||||
/<command> ids-for-ip <ipaddress> - Show player IDs that have logged in from given IP address
|
||||
|
||||
dmarker:
|
||||
description: Manipulate map markers
|
||||
@ -83,6 +84,8 @@ permissions:
|
||||
dynmap.resetstats: true
|
||||
dynmap.sendtoweb: true
|
||||
dynmap.purgequeue: true
|
||||
dynmap.ids-for-ip: true
|
||||
dynmap.ips-for-id: true
|
||||
dynmap.pause: true
|
||||
dynmap.marker.add: true
|
||||
dynmap.marker.update: true
|
||||
@ -144,6 +147,12 @@ permissions:
|
||||
dynmap.pause:
|
||||
description: Allows /dynmap pause
|
||||
default: op
|
||||
dynmap.ids-for-ip:
|
||||
description: Allows /dynmap ids-for-ip
|
||||
default: op
|
||||
dynmap.ips-for-id:
|
||||
description: Allows /dynmap ips-for-id
|
||||
default: op
|
||||
dynmap.marker.add:
|
||||
description: Allows /dmarker add
|
||||
default: op
|
||||
|
@ -11,6 +11,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST' && $_SESSION['lastchat'] < time())
|
||||
|
||||
$data = json_decode(trim(file_get_contents('php://input')));
|
||||
$data->timestamp = $timestamp;
|
||||
$data->ip = $_SERVER['REMOTE_ADDR'];
|
||||
$old_messages = json_decode(file_get_contents('dynmap_webchat.json'), true);
|
||||
if(!empty($old_messages))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user