From 645278773df0968d4eaea37d5af8263edfc453e9 Mon Sep 17 00:00:00 2001 From: Binal Patel Date: Tue, 1 Apr 2025 15:13:43 -0700 Subject: [PATCH 1/2] Add helper that relativizes and resolves child. --- api/src/org/labkey/vfs/FileSystemLike.java | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/api/src/org/labkey/vfs/FileSystemLike.java b/api/src/org/labkey/vfs/FileSystemLike.java index 647d9cd7b1e..1b277b32dad 100644 --- a/api/src/org/labkey/vfs/FileSystemLike.java +++ b/api/src/org/labkey/vfs/FileSystemLike.java @@ -222,6 +222,38 @@ static File toFile(FileLike f) return p.toFile(); } + // Converts an absolute URI to a relative one if it's within the base URI. + // If fileURI is outside rootURI, the result remains fileURI/unchanged. + // Examples: + // root "/a/b/c/", file "/x/y/z.txt" -> "/x/y/z.txt" + // root "/a/b/c/", file "/a/b/c/d.txt" -> "d.txt" + static URI getRelativeURI(URI rootURI, URI fileURI) + { + return rootURI.relativize(fileURI); + } + + static FileLike resolveChildWithRelativeURI(URI rootURI, URI fileURI) + { + URI relativeURI = getRelativeURI(rootURI, fileURI); + + // If the relative URI is absolute or remains unchanged, it means relativize failed and the file is outside the root directory. + if (relativeURI.isAbsolute() || relativeURI.equals(fileURI)) + { + throw new IllegalArgumentException("File '" + fileURI.getPath() + "' is outside the root '" + rootURI.getPath() + "'"); + } + + FileLike allowedRoot = new FileSystemLike.Builder(rootURI).root(); + + //explicitly check whether the given file path is within the allowed root directory + if (allowedRoot.getFileSystem().isDescendant(allowedRoot, fileURI)) + { + return allowedRoot.resolveChild(relativeURI.getPath()); + } + else + { + throw new IllegalArgumentException("File '" + relativeURI.getPath() + "' is not a descendant of '" + rootURI.getPath() + "'"); + } + } /* More efficient version of wrap when many files may be from the same directory */ static List wrapFiles(List files) From 873d4a8b97375a402a27619272183dc9340d9ac5 Mon Sep 17 00:00:00 2001 From: Binal Patel Date: Tue, 1 Apr 2025 20:58:45 -0700 Subject: [PATCH 2/2] Update the helper to take File as an argument and use URIUtil. --- api/src/org/labkey/vfs/FileSystemLike.java | 29 +++++++++------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/api/src/org/labkey/vfs/FileSystemLike.java b/api/src/org/labkey/vfs/FileSystemLike.java index 1b277b32dad..e19b0afb96f 100644 --- a/api/src/org/labkey/vfs/FileSystemLike.java +++ b/api/src/org/labkey/vfs/FileSystemLike.java @@ -222,28 +222,23 @@ static File toFile(FileLike f) return p.toFile(); } - // Converts an absolute URI to a relative one if it's within the base URI. - // If fileURI is outside rootURI, the result remains fileURI/unchanged. - // Examples: - // root "/a/b/c/", file "/x/y/z.txt" -> "/x/y/z.txt" - // root "/a/b/c/", file "/a/b/c/d.txt" -> "d.txt" - static URI getRelativeURI(URI rootURI, URI fileURI) + static FileLike resolveChildWithRelativeURI(File file) { - return rootURI.relativize(fileURI); - } + URI fileURI = file.toURI(); + FileLike allowedRoot = new FileSystemLike.Builder(fileURI).root(); - static FileLike resolveChildWithRelativeURI(URI rootURI, URI fileURI) - { - URI relativeURI = getRelativeURI(rootURI, fileURI); + // Converts an absolute URI to a relative one if it's within the base URI. + // If fileURI is outside rootURI, the result remains fileURI/unchanged. + // Examples: + // root "/a/b/c/", file "/x/y/z.txt" -> "/x/y/z.txt" + // root "/a/b/c/", file "/a/b/c/d.txt" -> "d.txt" + URI relativeURI = URIUtil.relativize(allowedRoot.toURI(), fileURI); - // If the relative URI is absolute or remains unchanged, it means relativize failed and the file is outside the root directory. - if (relativeURI.isAbsolute() || relativeURI.equals(fileURI)) + if (relativeURI == null) { - throw new IllegalArgumentException("File '" + fileURI.getPath() + "' is outside the root '" + rootURI.getPath() + "'"); + throw new IllegalArgumentException("File '" + fileURI.getPath() + "' is outside the root '" + allowedRoot.toURI().getPath() + "'"); } - FileLike allowedRoot = new FileSystemLike.Builder(rootURI).root(); - //explicitly check whether the given file path is within the allowed root directory if (allowedRoot.getFileSystem().isDescendant(allowedRoot, fileURI)) { @@ -251,7 +246,7 @@ static FileLike resolveChildWithRelativeURI(URI rootURI, URI fileURI) } else { - throw new IllegalArgumentException("File '" + relativeURI.getPath() + "' is not a descendant of '" + rootURI.getPath() + "'"); + throw new IllegalArgumentException("File '" + relativeURI.getPath() + "' is not a descendant of '" + allowedRoot.getPath() + "'"); } }