add schematic uploading + use template

This commit is contained in:
ayunami2000
2022-04-17 23:05:20 -04:00
parent 391e146d60
commit 16ee5378ad
18 changed files with 280 additions and 511 deletions

View File

@ -3,6 +3,8 @@ package dev.plex;
import dev.plex.cache.FileCache;
import dev.plex.config.ModuleConfig;
import dev.plex.module.PlexModule;
import dev.plex.request.AbstractServlet;
import dev.plex.request.SchematicUploadServlet;
import dev.plex.request.impl.AdminsEndpoint;
import dev.plex.request.impl.IndefBansEndpoint;
import dev.plex.request.impl.IndexEndpoint;
@ -11,7 +13,11 @@ import dev.plex.request.impl.PunishmentsEndpoint;
import dev.plex.request.impl.SchematicDownloadEndpoint;
import dev.plex.request.impl.SchematicUploadEndpoint;
import dev.plex.util.PlexLog;
import java.io.File;
import java.util.concurrent.atomic.AtomicReference;
import jakarta.servlet.MultipartConfigElement;
import lombok.Getter;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
@ -24,6 +30,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class HTTPDModule extends PlexModule
{
@ -38,6 +45,8 @@ public class HTTPDModule extends PlexModule
public static final FileCache fileCache = new FileCache();
public static final String template = AbstractServlet.readFileReal(HTTPDModule.class.getResourceAsStream("/httpd/template.html"));
@Override
public void load()
{
@ -75,6 +84,12 @@ public class HTTPDModule extends PlexModule
new SchematicDownloadEndpoint();
new SchematicUploadEndpoint();
ServletHolder uploadHolder = HTTPDModule.context.addServlet(SchematicUploadServlet.class, "/api/schematics/uploading");
File uploadLoc = new File(System.getProperty("java.io.tmpdir"), "schematic-temp-dir");
if (!uploadLoc.exists()) uploadLoc.mkdirs();
uploadHolder.getRegistration().setMultipartConfig(new MultipartConfigElement(uploadLoc.getAbsolutePath(), 1024 * 1024 * 5, 1024 * 1024 * 25, 1024 * 1024));
server.setConnectors(new Connector[]{connector});
server.setHandler(context);
@ -114,4 +129,34 @@ public class HTTPDModule extends PlexModule
permissions = rsp.getProvider();
return permissions != null;
}
public static File getWorldeditFolder()
{
if (Bukkit.getPluginManager().isPluginEnabled("WorldEdit"))
{
return new File(Bukkit.getPluginManager().getPlugin("WorldEdit").getDataFolder() + "/schematics/");
}
else if (Bukkit.getPluginManager().isPluginEnabled("FastAsyncWorldEdit"))
{
return new File(Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit").getDataFolder() + "/schematics/");
}
else
{
return null;
}
}
private static boolean isFileSystemCaseSensitive = !new File( "a" ).equals( new File( "A" ) );
public static boolean fileNameEquals(String filename1, String filename2)
{
if (isFileSystemCaseSensitive)
{
return filename1.equals(filename2);
}
else
{
return filename1.equalsIgnoreCase(filename2);
}
}
}

View File

@ -13,7 +13,7 @@ public class CacheItem
public CacheItem(File f) throws IOException
{
this.path = f.getPath();
this.file = f.length() >= 1048576 ? null : Files.readAllBytes(f.toPath());
this.file = Files.readAllBytes(f.toPath());
this.timestamp = System.currentTimeMillis();
}
}

View File

@ -1,9 +1,12 @@
package dev.plex.cache;
import com.google.common.collect.EvictingQueue;
import dev.plex.HTTPDModule;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Queue;
public class FileCache
@ -17,17 +20,17 @@ public class FileCache
public byte[] getFile(String path) throws IOException
{
CacheItem theItem = cache.stream().filter(cacheItem -> cacheItem.path.equals(path)).findFirst().orElse(null);
CacheItem theItem = cache.stream().filter(cacheItem -> HTTPDModule.fileNameEquals(cacheItem.path, path)).findFirst().orElse(null);
if (theItem == null)
{
theItem = new CacheItem(new File(path));
if (theItem.file != null) cache.add(theItem);
if (theItem.file.length < 1048576) cache.add(theItem);
}
if (System.currentTimeMillis() - theItem.timestamp > 3 * 60 * 1000) // 3 minutes
{
cache.remove(theItem);
theItem = new CacheItem(new File(path));
if (theItem.file != null) cache.add(theItem);
if (theItem.file.length < 1048576) cache.add(theItem);
}
return theItem.file;
}

View File

@ -15,6 +15,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import lombok.Data;
@ -87,7 +88,25 @@ public class AbstractServlet extends HttpServlet
});
}
public String readFile(InputStream filename)
public static String readFile(InputStream filename)
{
String base = HTTPDModule.template;
String page = readFileReal(filename);
String[] info = page.split("\n", 3);
System.out.println(Arrays.toString(info));
base = base.replace("${TITLE}", info[0]);
base = base.replace("${ACTIVE_" + info[1] + "}", "active\" aria-current=\"page");
base = base.replace("${ACTIVE_HOME}", "");
base = base.replace("${ACTIVE_ADMINS}", "");
base = base.replace("${ACTIVE_INDEFBANS}", "");
base = base.replace("${ACTIVE_LIST}", "");
base = base.replace("${ACTIVE_PUNISHMENTS}", "");
base = base.replace("${ACTIVE_SCHEMATICS}", "");
base = base.replace("${CONTENT}", info[2]);
return base;
}
public static String readFileReal(InputStream filename)
{
StringBuilder contentBuilder = new StringBuilder();
try
@ -96,7 +115,7 @@ public class AbstractServlet extends HttpServlet
String str;
while ((str = in.readLine()) != null)
{
contentBuilder.append(str);
contentBuilder.append(str).append("\n");
}
in.close();
}

View File

@ -0,0 +1,70 @@
package dev.plex.request;
import dev.plex.HTTPDModule;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.regex.Pattern;
public class SchematicUploadServlet extends HttpServlet
{
private static final Pattern schemNameMatcher = Pattern.compile("^[a-z0-9'!,_ -]{1,30}\\.schem(atic)?$", Pattern.CASE_INSENSITIVE);
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
File worldeditFolder = HTTPDModule.getWorldeditFolder();
if (worldeditFolder == null)
{
resp.getWriter().println(schematicUploadBadHTML("Worldedit is not installed!"));
return;
}
File[] schematics = worldeditFolder.listFiles();
Part uploadPart = null;
try
{
uploadPart = req.getPart("file");
}
catch (IllegalStateException e)
{
resp.getWriter().println(schematicUploadBadHTML("That schematic is too large!"));
return;
}
String filename = uploadPart.getSubmittedFileName().replaceAll("[^a-zA-Z0-9'!,_ .-]", "_");
if (schemNameMatcher.matcher(filename).matches())
{
boolean alreadyExists = schematics != null && Arrays.stream(schematics).anyMatch(file -> HTTPDModule.fileNameEquals(file.getName(), filename));
if (alreadyExists)
{
resp.getWriter().println(schematicUploadBadHTML("A schematic with the name <b>" + filename + "</b> already exists!"));
return;
}
InputStream inputStream = uploadPart.getInputStream();
Files.copy(inputStream, new File(worldeditFolder, filename).toPath(), StandardCopyOption.REPLACE_EXISTING);
inputStream.close();
resp.getWriter().println(schematicUploadGoodHTML("Successfully uploaded <b>" + filename + "."));
}
}
private String schematicUploadBadHTML(String message)
{
String file = AbstractServlet.readFile(this.getClass().getResourceAsStream("/httpd/schematic_upload_bad.html"));
file = file.replace("${MESSAGE}", message);
return file;
}
private String schematicUploadGoodHTML(String message)
{
String file = AbstractServlet.readFile(this.getClass().getResourceAsStream("/httpd/schematic_upload_good.html"));
file = file.replace("${MESSAGE}", message);
return file;
}
}

View File

@ -9,7 +9,6 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import org.bukkit.Bukkit;
public class SchematicDownloadEndpoint extends AbstractServlet
{
@ -36,25 +35,9 @@ public class SchematicDownloadEndpoint extends AbstractServlet
}
}
private File getWorldeditFolder()
{
if (Bukkit.getPluginManager().isPluginEnabled("WorldEdit"))
{
return new File(Bukkit.getPluginManager().getPlugin("WorldEdit").getDataFolder() + "/schematics/");
}
else if (Bukkit.getPluginManager().isPluginEnabled("FastAsyncWorldEdit"))
{
return new File(Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit").getDataFolder() + "/schematics/");
}
else
{
return null;
}
}
private void schematicServe(String requestedSchematic, OutputStream outputStream)
{
File worldeditFolder = getWorldeditFolder();
File worldeditFolder = HTTPDModule.getWorldeditFolder();
if (worldeditFolder == null)
{
return;
@ -83,7 +66,7 @@ public class SchematicDownloadEndpoint extends AbstractServlet
private String schematicHTML()
{
String file = readFile(this.getClass().getResourceAsStream("/httpd/schematic_download.html"));
File worldeditFolder = getWorldeditFolder();
File worldeditFolder = HTTPDModule.getWorldeditFolder();
if (worldeditFolder == null)
{
return null;

View File

@ -8,7 +8,7 @@ import jakarta.servlet.http.HttpServletResponse;
public class SchematicUploadEndpoint extends AbstractServlet
{
@GetMapping(endpoint = "/api/schematics/upload/")
public String downloadSchematic(HttpServletRequest request, HttpServletResponse response)
public String uploadSchematic(HttpServletRequest request, HttpServletResponse response)
{
return readFile(this.getClass().getResourceAsStream("/httpd/schematic_upload.html"));
}