From 052e7a7ae51ba802837bf74313e27db8e57e363e Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 26 Jun 2024 19:48:18 +0100 Subject: [PATCH] Make FileSystem.toLocal private Use a custom to-local function in the various ArchiveMounts, which don't faff around with sanitising paths. --- .../shared/computer/core/ResourceMount.java | 6 +++--- .../core/filesystem/ArchiveMount.java | 19 +++++++++++++++++++ .../core/filesystem/FileSystem.java | 4 ++-- .../core/filesystem/JarMount.java | 5 ++--- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/core/ResourceMount.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/core/ResourceMount.java index 2171ac6d4..6e4883c10 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/core/ResourceMount.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/core/ResourceMount.java @@ -7,7 +7,6 @@ package dan200.computercraft.shared.computer.core; import com.google.common.annotations.VisibleForTesting; import dan200.computercraft.api.filesystem.FileOperationException; import dan200.computercraft.core.filesystem.ArchiveMount; -import dan200.computercraft.core.filesystem.FileSystem; import net.minecraft.ResourceLocationException; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; @@ -65,9 +64,10 @@ public final class ResourceMount extends ArchiveMount { existingNamespace = file.getNamespace(); if (!file.getNamespace().equals(namespace)) continue; - if (!FileSystem.contains(subPath, file.getPath())) continue; // Some packs seem to include the parent? - var localPath = FileSystem.toLocal(file.getPath(), subPath); + var localPath = getLocalPath(file.getPath(), subPath); + if (localPath == null) continue; + try { getOrCreateChild(newRoot, localPath, this::createEntry); } catch (ResourceLocationException e) { diff --git a/projects/core/src/main/java/dan200/computercraft/core/filesystem/ArchiveMount.java b/projects/core/src/main/java/dan200/computercraft/core/filesystem/ArchiveMount.java index 5b22a998e..bac283ad9 100644 --- a/projects/core/src/main/java/dan200/computercraft/core/filesystem/ArchiveMount.java +++ b/projects/core/src/main/java/dan200/computercraft/core/filesystem/ArchiveMount.java @@ -8,6 +8,7 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import dan200.computercraft.core.apis.handles.ArrayByteChannel; +import javax.annotation.Nullable; import java.io.IOException; import java.nio.channels.SeekableByteChannel; import java.util.concurrent.TimeUnit; @@ -82,6 +83,24 @@ public abstract class ArchiveMount> extends */ protected abstract byte[] getFileContents(String path, T file) throws IOException; + /** + * Convert an absolute path to one relative to {@code root}. If this path is not a child of {@code root}, return + * {@code null}. + * + * @param path The full path. + * @param root The root directory to be relative to. + * @return The relativised path, or {@code null}. + */ + protected static @Nullable String getLocalPath(String path, String root) { + // Some packs seem to include files not under the root, so drop them immediately. + if (!path.startsWith(root)) return null; + + if (path.length() == root.length()) return ""; + + if (path.charAt(root.length()) != '/') return null; + return path.substring(root.length() + 1); + } + protected static class FileEntry> extends AbstractInMemoryMount.FileEntry { long size = -1; } diff --git a/projects/core/src/main/java/dan200/computercraft/core/filesystem/FileSystem.java b/projects/core/src/main/java/dan200/computercraft/core/filesystem/FileSystem.java index fb27eebd7..8a189d64f 100644 --- a/projects/core/src/main/java/dan200/computercraft/core/filesystem/FileSystem.java +++ b/projects/core/src/main/java/dan200/computercraft/core/filesystem/FileSystem.java @@ -404,7 +404,7 @@ public class FileSystem { return String.join("/", outputParts); } - public static boolean contains(String pathA, String pathB) { + private static boolean contains(String pathA, String pathB) { pathA = sanitizePath(pathA).toLowerCase(Locale.ROOT); pathB = sanitizePath(pathB).toLowerCase(Locale.ROOT); @@ -421,7 +421,7 @@ public class FileSystem { } } - public static String toLocal(String path, String location) { + static String toLocal(String path, String location) { path = sanitizePath(path); location = sanitizePath(location); diff --git a/projects/core/src/main/java/dan200/computercraft/core/filesystem/JarMount.java b/projects/core/src/main/java/dan200/computercraft/core/filesystem/JarMount.java index ebd975612..635c1a076 100644 --- a/projects/core/src/main/java/dan200/computercraft/core/filesystem/JarMount.java +++ b/projects/core/src/main/java/dan200/computercraft/core/filesystem/JarMount.java @@ -49,10 +49,9 @@ public final class JarMount extends ArchiveMount implements while (zipEntries.hasMoreElements()) { var entry = zipEntries.nextElement(); - var entryPath = entry.getName(); - if (!entryPath.startsWith(subPath)) continue; + var localPath = getLocalPath(entry.getName(), subPath); + if (localPath == null) continue; - var localPath = FileSystem.toLocal(entryPath, subPath); getOrCreateChild(root, localPath, x -> new FileEntry()).setup(entry); } }