diff --git a/src/main/java/dev/plex/HTTPDModule.java b/src/main/java/dev/plex/HTTPDModule.java index 31d76ab..c3179bf 100644 --- a/src/main/java/dev/plex/HTTPDModule.java +++ b/src/main/java/dev/plex/HTTPDModule.java @@ -1,5 +1,6 @@ package dev.plex; +import dev.plex.cache.FileCache; import dev.plex.config.ModuleConfig; import dev.plex.module.PlexModule; import dev.plex.request.impl.AdminsEndpoint; @@ -35,6 +36,8 @@ public class HTTPDModule extends PlexModule public static ModuleConfig moduleConfig; + public static final FileCache fileCache = new FileCache(); + @Override public void load() { diff --git a/src/main/java/dev/plex/cache/CacheItem.java b/src/main/java/dev/plex/cache/CacheItem.java new file mode 100644 index 0000000..6acba9a --- /dev/null +++ b/src/main/java/dev/plex/cache/CacheItem.java @@ -0,0 +1,19 @@ +package dev.plex.cache; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class CacheItem +{ + public String path; + public byte[] file; + public long timestamp; + + public CacheItem(File f) throws IOException + { + this.path = f.getPath(); + this.file = Files.readAllBytes(f.toPath()); + this.timestamp = System.currentTimeMillis(); + } +} diff --git a/src/main/java/dev/plex/cache/FileCache.java b/src/main/java/dev/plex/cache/FileCache.java new file mode 100644 index 0000000..6feb866 --- /dev/null +++ b/src/main/java/dev/plex/cache/FileCache.java @@ -0,0 +1,34 @@ +package dev.plex.cache; + +import com.google.common.collect.EvictingQueue; + +import java.io.File; +import java.io.IOException; +import java.util.Queue; + +public class FileCache +{ + private final Queue cache = EvictingQueue.create(15); + + public byte[] getFile(File file) throws IOException + { + return getFile(file.getPath()); + } + + public byte[] getFile(String path) throws IOException + { + CacheItem theItem = cache.stream().filter(cacheItem -> cacheItem.path.equals(path)).findFirst().orElse(null); + if (theItem == null) + { + theItem = new CacheItem(new File(path)); + cache.add(theItem); + } + if (System.currentTimeMillis() - theItem.timestamp > 3 * 60 * 1000) // 3 minutes + { + cache.remove(theItem); + theItem = new CacheItem(new File(path)); + cache.add(theItem); + } + return theItem.file; + } +} diff --git a/src/main/java/dev/plex/request/AbstractServlet.java b/src/main/java/dev/plex/request/AbstractServlet.java index 82b092b..d32d76f 100644 --- a/src/main/java/dev/plex/request/AbstractServlet.java +++ b/src/main/java/dev/plex/request/AbstractServlet.java @@ -46,7 +46,7 @@ public class AbstractServlet extends HttpServlet public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String ipAddress = req.getRemoteAddr(); - if (ipAddress == null) + if (ipAddress.equals("127.0.0.1")) { ipAddress = req.getHeader("X-FORWARDED-FOR"); } @@ -72,8 +72,8 @@ public class AbstractServlet extends HttpServlet resp.setStatus(HttpServletResponse.SC_OK); try { - Object object = mapping.method.invoke(this, req); - resp.getWriter().println(object.toString()); + Object object = mapping.method.invoke(this, req, resp); + if (object != null) resp.getWriter().println(object.toString()); } catch (IOException | IllegalAccessException | InvocationTargetException e) { diff --git a/src/main/java/dev/plex/request/impl/AdminsEndpoint.java b/src/main/java/dev/plex/request/impl/AdminsEndpoint.java index 0331013..5f8b111 100644 --- a/src/main/java/dev/plex/request/impl/AdminsEndpoint.java +++ b/src/main/java/dev/plex/request/impl/AdminsEndpoint.java @@ -14,6 +14,8 @@ import dev.plex.util.adapter.LocalDateTimeSerializer; import jakarta.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.util.stream.Collectors; + +import jakarta.servlet.http.HttpServletResponse; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; @@ -22,7 +24,7 @@ public class AdminsEndpoint extends AbstractServlet private static final String TITLE = "Admins - Plex HTTPD"; @GetMapping(endpoint = "/api/admins/") - public String getAdmins(HttpServletRequest request) + public String getAdmins(HttpServletRequest request, HttpServletResponse response) { String ipAddress = request.getRemoteAddr(); if (ipAddress == null) diff --git a/src/main/java/dev/plex/request/impl/IndefBansEndpoint.java b/src/main/java/dev/plex/request/impl/IndefBansEndpoint.java index e35637f..4721e6a 100644 --- a/src/main/java/dev/plex/request/impl/IndefBansEndpoint.java +++ b/src/main/java/dev/plex/request/impl/IndefBansEndpoint.java @@ -10,6 +10,7 @@ import dev.plex.request.AbstractServlet; import dev.plex.request.GetMapping; import dev.plex.util.PlexLog; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; @@ -18,7 +19,7 @@ public class IndefBansEndpoint extends AbstractServlet private static final String TITLE = "Indefinite Bans - Plex HTTPD"; @GetMapping(endpoint = "/api/indefbans/") - public String getBans(HttpServletRequest request) + public String getBans(HttpServletRequest request, HttpServletResponse response) { String ipAddress = request.getRemoteAddr(); if (ipAddress == null) diff --git a/src/main/java/dev/plex/request/impl/IndexEndpoint.java b/src/main/java/dev/plex/request/impl/IndexEndpoint.java index edb66f9..b3f02a3 100644 --- a/src/main/java/dev/plex/request/impl/IndexEndpoint.java +++ b/src/main/java/dev/plex/request/impl/IndexEndpoint.java @@ -3,18 +3,19 @@ package dev.plex.request.impl; import dev.plex.request.AbstractServlet; import dev.plex.request.GetMapping; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.bukkit.Bukkit; public class IndexEndpoint extends AbstractServlet { @GetMapping(endpoint = "//") - public String getIndex(HttpServletRequest request) + public String getIndex(HttpServletRequest request, HttpServletResponse response) { return indexHTML(); } @GetMapping(endpoint = "/api/") - public String getAPI(HttpServletRequest request) + public String getAPI(HttpServletRequest request, HttpServletResponse response) { return indexHTML(); } diff --git a/src/main/java/dev/plex/request/impl/ListEndpoint.java b/src/main/java/dev/plex/request/impl/ListEndpoint.java index 8b6fcf5..c9ae9f1 100644 --- a/src/main/java/dev/plex/request/impl/ListEndpoint.java +++ b/src/main/java/dev/plex/request/impl/ListEndpoint.java @@ -6,6 +6,8 @@ import dev.plex.request.GetMapping; import jakarta.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; + +import jakarta.servlet.http.HttpServletResponse; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -14,7 +16,7 @@ public class ListEndpoint extends AbstractServlet List players = new ArrayList<>(); @GetMapping(endpoint = "/api/list/") - public String getOnlinePlayers(HttpServletRequest request) + public String getOnlinePlayers(HttpServletRequest request, HttpServletResponse response) { for (Player player : Bukkit.getOnlinePlayers()) { diff --git a/src/main/java/dev/plex/request/impl/PunishmentsEndpoint.java b/src/main/java/dev/plex/request/impl/PunishmentsEndpoint.java index 0db0fd8..243163e 100644 --- a/src/main/java/dev/plex/request/impl/PunishmentsEndpoint.java +++ b/src/main/java/dev/plex/request/impl/PunishmentsEndpoint.java @@ -13,13 +13,15 @@ import dev.plex.util.adapter.LocalDateTimeSerializer; import jakarta.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.util.UUID; + +import jakarta.servlet.http.HttpServletResponse; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; public class PunishmentsEndpoint extends AbstractServlet { @GetMapping(endpoint = "/api/punishments/") - public String getPunishments(HttpServletRequest request) + public String getPunishments(HttpServletRequest request, HttpServletResponse response) { String ipAddress = request.getRemoteAddr(); if (ipAddress == null) diff --git a/src/main/java/dev/plex/request/impl/SchematicDownloadEndpoint.java b/src/main/java/dev/plex/request/impl/SchematicDownloadEndpoint.java index 81b3074..88aef7b 100644 --- a/src/main/java/dev/plex/request/impl/SchematicDownloadEndpoint.java +++ b/src/main/java/dev/plex/request/impl/SchematicDownloadEndpoint.java @@ -1,50 +1,92 @@ package dev.plex.request.impl; +import dev.plex.HTTPDModule; import dev.plex.request.AbstractServlet; import dev.plex.request.GetMapping; import jakarta.servlet.http.HttpServletRequest; import java.io.File; +import java.io.IOException; +import java.io.OutputStream; import java.util.Arrays; + +import jakarta.servlet.http.HttpServletResponse; import org.bukkit.Bukkit; public class SchematicDownloadEndpoint extends AbstractServlet { @GetMapping(endpoint = "/api/schematics/download/") - public String downloadSchematics(HttpServletRequest request) + public String downloadSchematics(HttpServletRequest request, HttpServletResponse response) { - return schematicHTML(); + if (request.getPathInfo() == null || request.getPathInfo().equals("/")) + { + return schematicHTML(); + } + else + { + OutputStream outputStream = null; + try { + outputStream = response.getOutputStream(); + } catch (IOException e) { + return null; + } + schematicServe(request.getPathInfo().replace("/", ""), outputStream); + return null; + } } - private String schematicHTML() + private File getWorldeditFolder() { - String file = readFile(this.getClass().getResourceAsStream("/httpd/schematic_list.html")); - File worldeditFolder; if (Bukkit.getPluginManager().isPluginEnabled("WorldEdit")) { - worldeditFolder = new File(Bukkit.getPluginManager().getPlugin("WorldEdit").getDataFolder() + "/schematics/"); + return new File(Bukkit.getPluginManager().getPlugin("WorldEdit").getDataFolder() + "/schematics/"); } else if (Bukkit.getPluginManager().isPluginEnabled("FastAsyncWorldEdit")) { - worldeditFolder = new File(Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit").getDataFolder() + "/schematics/"); + return new File(Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit").getDataFolder() + "/schematics/"); } else { return null; } + } + + private void schematicServe(String requestedSchematic, OutputStream outputStream) + { + File worldeditFolder = getWorldeditFolder(); + if (worldeditFolder == null) return; + File[] schems = worldeditFolder.listFiles(); + if (schems != null) + { + File schemFile = Arrays.stream(schems).filter(file -> file.getName().equals(requestedSchematic)).findFirst().orElse(null); + if (schemFile != null) + { + try + { + outputStream.write(HTTPDModule.fileCache.getFile(schemFile)); + } catch (IOException ignored) {} + } + } + } + + private String schematicHTML() + { + String file = readFile(this.getClass().getResourceAsStream("/httpd/schematic_list.html")); + File worldeditFolder = getWorldeditFolder(); + if (worldeditFolder == null) return null; StringBuilder sb = new StringBuilder(); File[] alphabetical = worldeditFolder.listFiles(); if (alphabetical != null) { Arrays.sort(alphabetical); + for (File worldeditFile : alphabetical) + { + sb.append("" + + "" + worldeditFile.getName() + "" + + "" + worldeditFile.length() + "B" + "" + + ""); + } + file = file.replace("${schematics}", sb.toString()); } - for (File worldeditFile : alphabetical) - { - sb.append("" + - "" + worldeditFile.getName() + "" + - "" + worldeditFile.length() + "B" + "" + - ""); - } - file = file.replace("${schematics}", sb.toString()); return file; } } diff --git a/src/main/java/dev/plex/request/impl/SchematicIndexEndpoint.java b/src/main/java/dev/plex/request/impl/SchematicIndexEndpoint.java index 4cbad89..42a712b 100644 --- a/src/main/java/dev/plex/request/impl/SchematicIndexEndpoint.java +++ b/src/main/java/dev/plex/request/impl/SchematicIndexEndpoint.java @@ -3,11 +3,12 @@ package dev.plex.request.impl; import dev.plex.request.AbstractServlet; import dev.plex.request.GetMapping; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; public class SchematicIndexEndpoint extends AbstractServlet { @GetMapping(endpoint = "/api/schematics/") - public String schematicIndex(HttpServletRequest request) + public String schematicIndex(HttpServletRequest request, HttpServletResponse response) { return readFile(this.getClass().getResourceAsStream("/httpd/schematic_list.html")); }