diff --git a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java index 8c8e117fa..5c2ee7466 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java +++ b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java @@ -91,10 +91,8 @@ public class ServerSchematicLoader { } public void handleNewUpload(ServerPlayerEntity player, String schematic, long size, BlockPos pos) { - String playerPath = getSchematicPath() + "/" + player.getName() - .getFormattedText(); - String playerSchematicId = player.getName() - .getFormattedText() + "/" + schematic; + String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName(); + String playerSchematicId = player.getGameProfile().getName() + "/" + schematic; FilesHelper.createFolderIfMissing(playerPath); // Unsupported Format @@ -103,6 +101,14 @@ public class ServerSchematicLoader { return; } + Path schematicPath = Paths.get(getSchematicPath()).toAbsolutePath(); + + Path uploadPath = schematicPath.resolve(playerSchematicId).normalize(); + if (!uploadPath.startsWith(schematicPath)) { + Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); + return; + } + // Too big if (!validateSchematicSizeOnServer(player, size)) return; @@ -117,12 +123,13 @@ public class ServerSchematicLoader { if (table == null) return; - // Delete schematic with same name - Files.deleteIfExists(Paths.get(getSchematicPath(), playerSchematicId)); - // Too many Schematics - Stream list = Files.list(Paths.get(playerPath)); - if (list.count() >= getConfig().maxSchematics.get()) { + long count; + try (Stream list = Files.list(Paths.get(playerPath))) { + count = list.count(); + } + + if (count >= getConfig().maxSchematics.get()) { Stream list2 = Files.list(Paths.get(playerPath)); Optional lastFilePath = list2.filter(f -> !Files.isDirectory(f)) .min(Comparator.comparingLong(f -> f.toFile() @@ -132,11 +139,9 @@ public class ServerSchematicLoader { Files.deleteIfExists(lastFilePath.get()); } } - list.close(); // Open Stream - OutputStream writer = - Files.newOutputStream(Paths.get(getSchematicPath(), playerSchematicId), StandardOpenOption.CREATE_NEW); + OutputStream writer = Files.newOutputStream(uploadPath); activeUploads.put(playerSchematicId, new SchematicUploadEntry(writer, size, player.getServerWorld(), pos)); // Notify Tile Entity @@ -165,8 +170,7 @@ public class ServerSchematicLoader { } public void handleWriteRequest(ServerPlayerEntity player, String schematic, byte[] data) { - String playerSchematicId = player.getName() - .getFormattedText() + "/" + schematic; + String playerSchematicId = player.getGameProfile().getName() + "/" + schematic; if (activeUploads.containsKey(playerSchematicId)) { SchematicUploadEntry entry = activeUploads.get(playerSchematicId); @@ -236,8 +240,7 @@ public class ServerSchematicLoader { } public void handleFinishedUpload(ServerPlayerEntity player, String schematic) { - String playerSchematicId = player.getName() - .getFormattedText() + "/" + schematic; + String playerSchematicId = player.getGameProfile().getName() + "/" + schematic; if (activeUploads.containsKey(playerSchematicId)) { try { @@ -258,8 +261,7 @@ public class ServerSchematicLoader { if (table == null) return; table.finishUpload(); - table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getName() - .getFormattedText())); + table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getGameProfile().getName())); } catch (IOException e) { Create.logger.error("Exception Thrown when finishing Upload: " + playerSchematicId); @@ -270,15 +272,21 @@ public class ServerSchematicLoader { public void handleInstantSchematic(ServerPlayerEntity player, String schematic, World world, BlockPos pos, BlockPos bounds) { - String playerPath = getSchematicPath() + "/" + player.getName() - .getFormattedText(); - String playerSchematicId = player.getName() - .getFormattedText() + "/" + schematic; + String playerPath = getSchematicPath() + "/" + player.getGameProfile().getName(); + String playerSchematicId = player.getGameProfile().getName() + "/" + schematic; FilesHelper.createFolderIfMissing(playerPath); // Unsupported Format if (!schematic.endsWith(".nbt")) { - Create.logger.warn("Attempted Schematic Upload with non-supported Format: " + playerSchematicId); + Create.logger.warn("Attempted Schematic Upload with non-supported Format: {}", playerSchematicId); + return; + } + + Path schematicPath = Paths.get(getSchematicPath()).toAbsolutePath(); + + Path path = schematicPath.resolve(playerSchematicId).normalize(); + if (!path.startsWith(schematicPath)) { + Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); return; } @@ -287,39 +295,32 @@ public class ServerSchematicLoader { return; try { - // Delete schematic with same name - Path path = Paths.get(getSchematicPath(), playerSchematicId); - Files.deleteIfExists(path); - // Too many Schematics - Stream list = Files.list(Paths.get(playerPath)); - if (list.count() >= getConfig().maxSchematics.get()) { + long count; + try (Stream list = Files.list(Paths.get(playerPath))) { + count = list.count(); + } + + if (count >= getConfig().maxSchematics.get()) { Stream list2 = Files.list(Paths.get(playerPath)); Optional lastFilePath = list2.filter(f -> !Files.isDirectory(f)) .min(Comparator.comparingLong(f -> f.toFile() .lastModified())); list2.close(); - if (lastFilePath.isPresent()) + if (lastFilePath.isPresent()) Files.deleteIfExists(lastFilePath.get()); } - list.close(); Template t = new Template(); t.takeBlocksFromWorld(world, pos, bounds, true, Blocks.AIR); - OutputStream outputStream = null; - try { - outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE); + try (OutputStream outputStream = Files.newOutputStream(path)) { CompoundNBT nbttagcompound = t.writeToNBT(new CompoundNBT()); CompressedStreamTools.writeCompressed(nbttagcompound, outputStream); - player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getName() - .getFormattedText())); + player.setHeldItem(Hand.MAIN_HAND, SchematicItem.create(schematic, player.getGameProfile().getName())); } catch (IOException e) { e.printStackTrace(); - } finally { - if (outputStream != null) - IOUtils.closeQuietly(outputStream); } } catch (IOException e) { Create.logger.error("Exception Thrown in direct Schematic Upload: " + playerSchematicId); diff --git a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java index ac7771002..a07437758 100644 --- a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java @@ -3,13 +3,15 @@ package com.simibubi.create.content.schematics.item; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.List; import javax.annotation.Nonnull; -import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import com.simibubi.create.AllItems; import com.simibubi.create.content.schematics.SchematicProcessor; @@ -46,6 +48,8 @@ import net.minecraftforge.fml.common.thread.SidedThreadGroups; public class SchematicItem extends Item { + private static final Logger LOGGER = LogManager.getLogger(); + public SchematicItem(Properties properties) { super(properties.maxStackSize(1)); } @@ -106,25 +110,29 @@ public class SchematicItem extends Item { String schematic = blueprint.getTag() .getString("File"); - String filepath = ""; + if (!schematic.endsWith(".nbt")) + return t; - if (Thread.currentThread() - .getThreadGroup() == SidedThreadGroups.SERVER) - filepath = "schematics/uploaded/" + owner + "/" + schematic; - else - filepath = "schematics/" + schematic; + Path dir; + Path file; - InputStream stream = null; - try { - stream = Files.newInputStream(Paths.get(filepath), StandardOpenOption.READ); + if (Thread.currentThread().getThreadGroup() == SidedThreadGroups.SERVER) { + dir = Paths.get("schematics", "uploaded").toAbsolutePath(); + file = Paths.get(owner, schematic); + } else { + dir = Paths.get("schematics").toAbsolutePath(); + file = Paths.get(schematic); + } + + Path path = dir.resolve(file).normalize(); + if (!path.startsWith(dir)) + return t; + + try (InputStream stream = Files.newInputStream(path, StandardOpenOption.READ)) { CompoundNBT nbt = CompressedStreamTools.readCompressed(stream); t.read(nbt); - } catch (IOException e) { - // Player/Server doesnt have schematic saved - } finally { - if (stream != null) - IOUtils.closeQuietly(stream); + LOGGER.warn("Failed to read schematic", e); } return t; diff --git a/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java b/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java index 67bc3f1fa..e59a45521 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java @@ -21,17 +21,10 @@ import net.minecraft.nbt.CompoundNBT; public class FilesHelper { public static void createFolderIfMissing(String name) { - Path path = Paths.get(name); - if (path.getParent() != null) - createFolderIfMissing(path.getParent() - .toString()); - - if (!Files.isDirectory(path)) { - try { - Files.createDirectory(path); - } catch (IOException e) { - Create.logger.warn("Could not create Folder: " + name); - } + try { + Files.createDirectories(Paths.get(name)); + } catch (IOException e) { + Create.logger.warn("Could not create Folder: {}", name); } }