From 23613d7a638f1f0df754eb04a0ea4eaf0425e355 Mon Sep 17 00:00:00 2001 From: Rsl1122 Date: Sat, 27 Oct 2018 11:51:36 +0300 Subject: [PATCH] [#752] Html Customization for favicon.ico file Added a new favicon.ico file that can be customized like all other web files, by placing a favicon.ico file to /plugins/Plan/web --- Plan/dependency-reduced-pom.xml | 1 + Plan/pom.xml | 1 + .../plan/system/file/PlanFiles.java | 5 ++ .../system/webserver/ResponseHandler.java | 4 +- .../plan/system/webserver/cache/PageId.java | 2 +- .../webserver/response/ByteResponse.java | 44 ++++++++++++++++++ .../webserver/response/ResponseFactory.java | 4 ++ .../webserver/response/ResponseType.java | 4 +- .../plan/utilities/file/FileUtil.java | 30 ++++++++++-- Plan/src/main/resources/web/favicon.ico | Bin 0 -> 1150 bytes 10 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ByteResponse.java create mode 100644 Plan/src/main/resources/web/favicon.ico diff --git a/Plan/dependency-reduced-pom.xml b/Plan/dependency-reduced-pom.xml index 617d9d013..4441b3970 100644 --- a/Plan/dependency-reduced-pom.xml +++ b/Plan/dependency-reduced-pom.xml @@ -20,6 +20,7 @@ **/*.js **/*.css locale/*.txt + **/*.ico diff --git a/Plan/pom.xml b/Plan/pom.xml index 29e3b0339..09de51fe9 100644 --- a/Plan/pom.xml +++ b/Plan/pom.xml @@ -223,6 +223,7 @@ **/*.js **/*.css locale/*.txt + **/*.ico diff --git a/Plan/src/main/java/com/djrapitops/plan/system/file/PlanFiles.java b/Plan/src/main/java/com/djrapitops/plan/system/file/PlanFiles.java index 748f6fc56..61e7b4e7d 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/file/PlanFiles.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/file/PlanFiles.java @@ -14,6 +14,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.List; /** @@ -110,6 +111,10 @@ public class PlanFiles implements SubSystem { )); } + public InputStream readCustomizableResource(String fileName) { + return FileUtil.stream(plugin, new File(plugin.getDataFolder(), fileName.replace("/", File.separator)), fileName); + } + private String flatten(List lines) { StringBuilder flat = new StringBuilder(); for (String line : lines) { diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/ResponseHandler.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/ResponseHandler.java index 340e42e6d..6c1fb0be3 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/ResponseHandler.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/ResponseHandler.java @@ -66,7 +66,6 @@ public class ResponseHandler extends TreePageHandler { } public void registerPages() { - registerPage("favicon.ico", responseFactory.redirectResponse("https://puu.sh/tK0KL/6aa2ba141b.ico"), 5); registerPage("debug", debugPageHandler); registerPage("players", playersPageHandler); registerPage("player", playerPageHandler); @@ -124,6 +123,9 @@ public class ResponseHandler extends TreePageHandler { if (targetString.endsWith(".js")) { return ResponseCache.loadResponse(PageId.JS.of(targetString), () -> responseFactory.javaScriptResponse(targetString)); } + if (targetString.endsWith("favicon.ico")) { + return ResponseCache.loadResponse(PageId.FAVICON.id(), responseFactory::faviconResponse); + } boolean isNotInfoRequest = target.isEmpty() || !target.get(0).equals("info"); boolean isAuthRequired = webServer.get().isAuthRequired() && isNotInfoRequest; if (isAuthRequired) { diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/cache/PageId.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/cache/PageId.java index 7aa38dd38..e00924ebe 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/cache/PageId.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/cache/PageId.java @@ -26,7 +26,7 @@ public enum PageId { JS("js:"), CSS("css:"), - FAVICON_REDIRECT("Redirect:Favicon"), + FAVICON("Favicon"), PLAYER_PLUGINS_TAB("playerPluginsTab:"), NETWORK_CONTENT("networkContent"); diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ByteResponse.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ByteResponse.java new file mode 100644 index 000000000..b5b7501ba --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ByteResponse.java @@ -0,0 +1,44 @@ +package com.djrapitops.plan.system.webserver.response; + +import com.djrapitops.plan.system.file.PlanFiles; +import com.djrapitops.plan.system.locale.Locale; +import com.djrapitops.plan.system.settings.theme.Theme; +import com.sun.net.httpserver.HttpExchange; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * {@link Response} for raw bytes. + * + * @author Rsl1122 + */ +public class ByteResponse extends Response { + + private final PlanFiles files; + private final String fileName; + + public ByteResponse(ResponseType type, String fileName, PlanFiles files) { + super(type); + this.fileName = fileName; + this.files = files; + + setHeader("HTTP/1.1 200 OK"); + } + + @Override + public void send(HttpExchange exchange, Locale locale, Theme theme) throws IOException { + responseHeaders.set("Accept-Ranges", "bytes"); + exchange.sendResponseHeaders(getCode(), 0); + + try (OutputStream out = exchange.getResponseBody(); + InputStream bis = files.readCustomizableResource(fileName)) { + byte[] buffer = new byte[2048]; + int count; + while ((count = bis.read(buffer)) != -1) { + out.write(buffer, 0, count); + } + } + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ResponseFactory.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ResponseFactory.java index 729019d30..9e9137b8e 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ResponseFactory.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ResponseFactory.java @@ -115,6 +115,10 @@ public class ResponseFactory { return new RedirectResponse(location); } + public Response faviconResponse() { + return new ByteResponse(ResponseType.X_ICON, "web/favicon.ico", files); + } + public ErrorResponse pageNotFound404() { return notFound404(locale.getString(ErrorPageLang.UNKNOWN_PAGE_404)); } diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ResponseType.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ResponseType.java index 85ea8b115..85a1f0799 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ResponseType.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/response/ResponseType.java @@ -13,7 +13,9 @@ public enum ResponseType { HTML("text/html; charset=utf-8"), CSS("text/css"), JSON("application/json"), - JAVASCRIPT("application/javascript"); + JAVASCRIPT("application/javascript"), + IMAGE("image/gif"), + X_ICON("image/x-icon"); private final String type; diff --git a/Plan/src/main/java/com/djrapitops/plan/utilities/file/FileUtil.java b/Plan/src/main/java/com/djrapitops/plan/utilities/file/FileUtil.java index 3d6cd366e..e50f5c684 100644 --- a/Plan/src/main/java/com/djrapitops/plan/utilities/file/FileUtil.java +++ b/Plan/src/main/java/com/djrapitops/plan/utilities/file/FileUtil.java @@ -4,10 +4,7 @@ import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.utilities.MiscUtils; import com.djrapitops.plugin.logging.L; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -34,6 +31,31 @@ public class FileUtil { return lines(plugin, defaults); } + public static InputStream stream(PlanPlugin plugin, File savedFile, String defaults) { + try { + if (savedFile.exists()) { + return stream(savedFile); + } else { + String fileName = savedFile.getName(); + File found = attemptToFind(fileName, new File(plugin.getDataFolder(), "web")); + if (found != null) { + return stream(found); + } + } + } catch (FileNotFoundException ignore) { + // File was not found, use jar version + } + return stream(plugin, defaults); + } + + private static InputStream stream(PlanPlugin plugin, String resource) { + return plugin.getResource(resource); + } + + private static InputStream stream(File savedFile) throws FileNotFoundException { + return new FileInputStream(savedFile); + } + /** * Breadth-First search through the file tree to find the file. * diff --git a/Plan/src/main/resources/web/favicon.ico b/Plan/src/main/resources/web/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..cea02dd443c390502f9d0be4f00f9aaab419d62d GIT binary patch literal 1150 zcmbu8!41MN3`Kth15`qSE4^{x%uJk_fDKrQWim(br?T`F?6xAV9H-xTzgDFHgFWL2 zThF-ffg^y6rAemDx)s2BS)5+C8s*_}tw~Pq6>-!OPW7pS{rW_FwJ4?hWHe99XRQ0R z9?FwtsHXeKL;Ew`&u24i{l4-#Q_Jh@+%EjExX36cf`7;=c2uzTdEO9ZHf7} Y$2-)+uHC`R+qw4+cn