mirror of
https://github.com/webbukkit/dynmap.git
synced 2024-12-28 19:47:45 +01:00
Merge in FrozenCow's latest Jetty updates
This commit is contained in:
commit
1f6eb62cc1
@ -7,6 +7,7 @@ import java.io.InputStream;
|
|||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.URL;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -30,11 +31,17 @@ import org.dynmap.hdmap.HDMapManager;
|
|||||||
import org.dynmap.hdmap.TexturePack;
|
import org.dynmap.hdmap.TexturePack;
|
||||||
import org.dynmap.markers.MarkerAPI;
|
import org.dynmap.markers.MarkerAPI;
|
||||||
import org.dynmap.markers.impl.MarkerAPIImpl;
|
import org.dynmap.markers.impl.MarkerAPIImpl;
|
||||||
|
import org.dynmap.web.BanIPFilter;
|
||||||
|
import org.dynmap.web.CustomHeaderFilter;
|
||||||
|
import org.dynmap.web.FilterHandler;
|
||||||
|
import org.dynmap.web.HandlerRouter;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.handler.ResourceHandler;
|
||||||
import org.eclipse.jetty.servlet.FilterHolder;
|
import org.eclipse.jetty.servlet.FilterHolder;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.util.resource.FileResource;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
import javax.servlet.*;
|
import javax.servlet.*;
|
||||||
@ -45,7 +52,7 @@ public class DynmapCore {
|
|||||||
private DynmapServerInterface server;
|
private DynmapServerInterface server;
|
||||||
private String version;
|
private String version;
|
||||||
private Server webServer = null;
|
private Server webServer = null;
|
||||||
private ServletContextHandler webServerContextHandler = null;
|
private HandlerRouter router = null;
|
||||||
public MapManager mapManager = null;
|
public MapManager mapManager = null;
|
||||||
public PlayerList playerList;
|
public PlayerList playerList;
|
||||||
public ConfigurationNode configuration;
|
public ConfigurationNode configuration;
|
||||||
@ -401,112 +408,65 @@ public class DynmapCore {
|
|||||||
return config_hashcode;
|
return config_hashcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FileResource createFileResource(String path) {
|
||||||
|
try {
|
||||||
|
return new FileResource(new URL("file://" + path));
|
||||||
|
} catch(Exception e) {
|
||||||
|
Log.info("Could not create file resource");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void loadWebserver() {
|
public void loadWebserver() {
|
||||||
webServer = new Server(new InetSocketAddress(configuration.getString("webserver-bindaddress", "0.0.0.0"), configuration.getInteger("webserver-port", 8123)));
|
webServer = new Server(new InetSocketAddress(configuration.getString("webserver-bindaddress", "0.0.0.0"), configuration.getInteger("webserver-port", 8123)));
|
||||||
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
|
||||||
context.setContextPath("/");
|
|
||||||
webServer.setHandler(context);
|
|
||||||
webServerContextHandler = context;
|
|
||||||
|
|
||||||
boolean allow_symlinks = configuration.getBoolean("allow-symlinks", false);
|
final boolean allow_symlinks = configuration.getBoolean("allow-symlinks", false);
|
||||||
int maxconnections = configuration.getInteger("max-sessions", 30);
|
int maxconnections = configuration.getInteger("max-sessions", 30);
|
||||||
if(maxconnections < 2) maxconnections = 2;
|
if(maxconnections < 2) maxconnections = 2;
|
||||||
|
router = new HandlerRouter() {{
|
||||||
|
this.addHandler("/", new ResourceHandler() {{
|
||||||
|
this.setAliases(allow_symlinks);
|
||||||
|
this.setWelcomeFiles(new String[] { "index.html" });
|
||||||
|
this.setDirectoriesListed(true);
|
||||||
|
this.setBaseResource(createFileResource(getFile(getWebPath()).getAbsolutePath()));
|
||||||
|
}});
|
||||||
|
this.addHandler("/tiles/*", new ResourceHandler() {{
|
||||||
|
this.setAliases(allow_symlinks);
|
||||||
|
this.setWelcomeFiles(new String[] { });
|
||||||
|
this.setDirectoriesListed(true);
|
||||||
|
this.setBaseResource(createFileResource(tilesDirectory.getAbsolutePath()));
|
||||||
|
}});
|
||||||
|
}};
|
||||||
|
|
||||||
if(allow_symlinks)
|
if(allow_symlinks)
|
||||||
Log.verboseinfo("Web server is permitting symbolic links");
|
Log.verboseinfo("Web server is permitting symbolic links");
|
||||||
else
|
else
|
||||||
Log.verboseinfo("Web server is not permitting symbolic links");
|
Log.verboseinfo("Web server is not permitting symbolic links");
|
||||||
|
|
||||||
org.eclipse.jetty.server.Server s = new org.eclipse.jetty.server.Server();
|
List<Filter> filters = new LinkedList<Filter>();
|
||||||
ServletHandler handler = new org.eclipse.jetty.servlet.ServletHandler();
|
|
||||||
s.setHandler(handler);
|
|
||||||
|
|
||||||
/* Check for banned IPs */
|
/* Check for banned IPs */
|
||||||
boolean checkbannedips = configuration.getBoolean("check-banned-ips", true);
|
boolean checkbannedips = configuration.getBoolean("check-banned-ips", true);
|
||||||
if (checkbannedips) {
|
if (checkbannedips) {
|
||||||
context.addFilter(new FilterHolder(new Filter() {
|
filters.add(new BanIPFilter(this));
|
||||||
private HashSet<String> banned_ips = new HashSet<String>();
|
|
||||||
private HashSet<String> banned_ips_notified = new HashSet<String>();
|
|
||||||
private long last_loaded = 0;
|
|
||||||
private static final long BANNED_RELOAD_INTERVAL = 15000; /* Every 15 seconds */
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(FilterConfig filterConfig) throws ServletException { }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
|
||||||
HttpServletResponse resp = (HttpServletResponse)response;
|
|
||||||
String ipaddr = request.getRemoteAddr();
|
|
||||||
if (isIpBanned(ipaddr)) {
|
|
||||||
Log.info("Rejected connection by banned IP address - " + ipaddr);
|
|
||||||
resp.sendError(403);
|
|
||||||
} else {
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadBannedIPs() {
|
|
||||||
banned_ips.clear();
|
|
||||||
banned_ips_notified.clear();
|
|
||||||
banned_ips.addAll(getServer().getIPBans());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return true if address is banned */
|
|
||||||
public boolean isIpBanned(String ipaddr) {
|
|
||||||
long t = System.currentTimeMillis();
|
|
||||||
if((t < last_loaded) || ((t-last_loaded) > BANNED_RELOAD_INTERVAL)) {
|
|
||||||
loadBannedIPs();
|
|
||||||
last_loaded = t;
|
|
||||||
}
|
|
||||||
if(banned_ips.contains(ipaddr)) {
|
|
||||||
if(!banned_ips_notified.contains(ipaddr)) {
|
|
||||||
banned_ips_notified.add(ipaddr);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() { }
|
|
||||||
}), "/*", null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load customized response headers, if any */
|
/* Load customized response headers, if any */
|
||||||
final ConfigurationNode custhttp = configuration.getNode("http-response-headers");
|
filters.add(new CustomHeaderFilter(configuration.getNode("http-response-headers")));
|
||||||
context.addFilter(new FilterHolder(new Filter() {
|
|
||||||
@Override
|
|
||||||
public void init(FilterConfig filterConfig) throws ServletException { }
|
|
||||||
|
|
||||||
@Override
|
webServer.setHandler(new FilterHandler(router, filters));
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
|
||||||
HttpServletResponse resp = (HttpServletResponse)response;
|
|
||||||
|
|
||||||
if(custhttp != null) {
|
|
||||||
for(String k : custhttp.keySet()) {
|
|
||||||
String v = custhttp.getString(k);
|
|
||||||
if(v != null) {
|
|
||||||
resp.setHeader(k, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroy() { }
|
|
||||||
}), "/*", null);
|
|
||||||
|
|
||||||
addServlet("/*", new org.dynmap.servlet.FileServlet(getFile(getWebPath()).getAbsolutePath(), allow_symlinks));
|
|
||||||
addServlet("/tiles/*", new org.dynmap.servlet.FileServlet(tilesDirectory.getAbsolutePath(), allow_symlinks));
|
|
||||||
addServlet("/up/configuration", new org.dynmap.servlet.ClientConfigurationServlet(this));
|
addServlet("/up/configuration", new org.dynmap.servlet.ClientConfigurationServlet(this));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<String> getIPBans() {
|
||||||
|
return getServer().getIPBans();
|
||||||
|
}
|
||||||
|
|
||||||
public void addServlet(String path, HttpServlet servlet) {
|
public void addServlet(String path, HttpServlet servlet) {
|
||||||
ServletHolder holder = new ServletHolder(servlet);
|
ServletHolder holder = new ServletHolder(servlet);
|
||||||
webServerContextHandler.getServletHandler().addServletWithMapping(holder, path);
|
router.addServlet(path, servlet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
62
src/main/java/org/dynmap/web/BanIPFilter.java
Normal file
62
src/main/java/org/dynmap/web/BanIPFilter.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package org.dynmap.web;
|
||||||
|
|
||||||
|
import org.dynmap.DynmapCore;
|
||||||
|
import org.dynmap.Log;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class BanIPFilter implements Filter {
|
||||||
|
private DynmapCore core;
|
||||||
|
private HashSet<String> banned_ips = new HashSet<String>();
|
||||||
|
private HashSet<String> banned_ips_notified = new HashSet<String>();
|
||||||
|
private long last_loaded = 0;
|
||||||
|
private long lastmod = 0;
|
||||||
|
private static final long BANNED_RELOAD_INTERVAL = 15000; /* Every 15 seconds */
|
||||||
|
|
||||||
|
public BanIPFilter(DynmapCore core) {
|
||||||
|
this.core = core;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
HttpServletResponse resp = (HttpServletResponse)response;
|
||||||
|
String ipaddr = request.getRemoteAddr();
|
||||||
|
if (isIpBanned(ipaddr)) {
|
||||||
|
Log.info("Rejected connection by banned IP address - " + ipaddr);
|
||||||
|
resp.sendError(403);
|
||||||
|
} else {
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadBannedIPs() {
|
||||||
|
banned_ips.clear();
|
||||||
|
banned_ips_notified.clear();
|
||||||
|
banned_ips.addAll(core.getIPBans());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return true if address is banned */
|
||||||
|
public boolean isIpBanned(String ipaddr) {
|
||||||
|
long t = System.currentTimeMillis();
|
||||||
|
if((t < last_loaded) || ((t-last_loaded) > BANNED_RELOAD_INTERVAL)) {
|
||||||
|
loadBannedIPs();
|
||||||
|
last_loaded = t;
|
||||||
|
}
|
||||||
|
if(banned_ips.contains(ipaddr)) {
|
||||||
|
if(!banned_ips_notified.contains(ipaddr)) {
|
||||||
|
banned_ips_notified.add(ipaddr);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() { }
|
||||||
|
}
|
38
src/main/java/org/dynmap/web/CustomHeaderFilter.java
Normal file
38
src/main/java/org/dynmap/web/CustomHeaderFilter.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package org.dynmap.web;
|
||||||
|
|
||||||
|
import org.dynmap.ConfigurationNode;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class CustomHeaderFilter implements Filter {
|
||||||
|
private final ConfigurationNode custhttp;
|
||||||
|
public CustomHeaderFilter(ConfigurationNode configuration) {
|
||||||
|
this.custhttp = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
|
HttpServletResponse resp = (HttpServletResponse) response;
|
||||||
|
|
||||||
|
if (custhttp != null) {
|
||||||
|
for (String k : custhttp.keySet()) {
|
||||||
|
String v = custhttp.getString(k);
|
||||||
|
if (v != null) {
|
||||||
|
resp.setHeader(k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
}
|
||||||
|
}
|
65
src/main/java/org/dynmap/web/FilterHandler.java
Normal file
65
src/main/java/org/dynmap/web/FilterHandler.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package org.dynmap.web;
|
||||||
|
|
||||||
|
import org.dynmap.Log;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
|
import org.eclipse.jetty.servlet.FilterHolder;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FilterHandler extends AbstractHandler {
|
||||||
|
private Handler handler;
|
||||||
|
private LinkedList<FilterHolder> filters = new LinkedList<FilterHolder>();
|
||||||
|
|
||||||
|
public FilterHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public FilterHandler(Handler handler, Iterable<Filter> filters) {
|
||||||
|
this.handler = handler;
|
||||||
|
for(Filter f : filters) {
|
||||||
|
this.filters.add(new FilterHolder(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Handler getHandler() {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHandler(Handler handler) {
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterable<FilterHolder> getFilters() {
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFilter(Filter filter) {
|
||||||
|
filters.add(new FilterHolder(filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(final String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
final Handler handler = this.getHandler();
|
||||||
|
final Iterator<FilterHolder> iterator = getFilters().iterator();
|
||||||
|
final FilterChain chain = new FilterChain() {
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest re, ServletResponse rs) throws IOException, ServletException {
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
Filter f = iterator.next().getFilter();
|
||||||
|
f.doFilter(request, response, this);
|
||||||
|
} else {
|
||||||
|
handler.handle(target, baseRequest, request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
60
src/main/java/org/dynmap/web/HandlerRouter.java
Normal file
60
src/main/java/org/dynmap/web/HandlerRouter.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package org.dynmap.web;
|
||||||
|
|
||||||
|
import org.dynmap.Log;
|
||||||
|
import org.eclipse.jetty.http.PathMap;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
|
|
||||||
|
import javax.servlet.Servlet;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class HandlerRouter extends AbstractHandler {
|
||||||
|
|
||||||
|
PathMap pathMap = new PathMap();
|
||||||
|
public HandlerRouter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHandler(String path, Handler handler) {
|
||||||
|
pathMap.put(path, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addServlet(String path, Servlet servlet) {
|
||||||
|
pathMap.put(path, servlet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
pathMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
|
String pathInfo = request.getPathInfo();
|
||||||
|
PathMap.Entry e = pathMap.getMatch(pathInfo);
|
||||||
|
String mappedPath = e.getMapped();
|
||||||
|
|
||||||
|
String childPathInfo = pathInfo;
|
||||||
|
if (mappedPath != null) {
|
||||||
|
int i = 0;
|
||||||
|
while(i<mappedPath.length() && mappedPath.charAt(i) == pathInfo.charAt(i)){ i++; }
|
||||||
|
childPathInfo = childPathInfo.substring(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
org.eclipse.jetty.server.Request r = (org.eclipse.jetty.server.Request)request;
|
||||||
|
r.setPathInfo(childPathInfo);
|
||||||
|
|
||||||
|
Object o = e.getValue();
|
||||||
|
if (o instanceof Handler) {
|
||||||
|
Handler h = (Handler)o;
|
||||||
|
h.handle(target, baseRequest, request, response);
|
||||||
|
} else if (o instanceof Servlet) {
|
||||||
|
Servlet s = (Servlet)o;
|
||||||
|
s.service(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
r.setPathInfo(pathInfo);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user