From ed472ac7fad7c8980671ee375030ecaab240b366 Mon Sep 17 00:00:00 2001 From: Stuart Douglas Date: Tue, 15 Feb 2022 11:11:47 +1100 Subject: [PATCH] Handle paths with a '?' in them This is actually quite tricky, as URI does not let you create these by default, you need to sneak them in using URL.toUrl(). If you attempt to use the URI constructor directly then a '?' is interpreted as the start of the query string, and %3f is encoded to %253f, so there is no way to actually pass in an ecoded question mark to the URI constructor. --- .../java/io/quarkus/fs/util/ZipUtils.java | 3 +- .../java/io/quarkus/fs/util/ZipUtilsTest.java | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/quarkus/fs/util/ZipUtils.java b/src/main/java/io/quarkus/fs/util/ZipUtils.java index 790e2f1..8cfcb59 100644 --- a/src/main/java/io/quarkus/fs/util/ZipUtils.java +++ b/src/main/java/io/quarkus/fs/util/ZipUtils.java @@ -5,6 +5,7 @@ import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.DirectoryStream; import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileSystem; @@ -65,7 +66,7 @@ public static void unzip(Path zipFile, Path targetDir) throws IOException { public static URI toZipUri(Path zipFile) throws IOException { URI zipUri = zipFile.toUri(); try { - zipUri = new URI(JAR_URI_PREFIX + zipUri.getScheme(), zipUri.getPath(), null); + zipUri = new URL(JAR_URI_PREFIX + zipUri.getScheme() + "://" + zipUri.getRawPath() + "!/").toURI(); } catch (URISyntaxException e) { throw new IOException("Failed to create a JAR URI for " + zipFile, e); } diff --git a/src/test/java/io/quarkus/fs/util/ZipUtilsTest.java b/src/test/java/io/quarkus/fs/util/ZipUtilsTest.java index bde902d..0ff1b22 100644 --- a/src/test/java/io/quarkus/fs/util/ZipUtilsTest.java +++ b/src/test/java/io/quarkus/fs/util/ZipUtilsTest.java @@ -12,6 +12,8 @@ import java.util.Collections; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; class ZipUtilsTest { @@ -74,6 +76,32 @@ public void testNewZip() throws Exception { } } + /** + * Test that the {@link ZipUtils#newZip(Path)} works as expected when the path contains a question mark + * + * Windows does not support question marks in file names + * + * @throws Exception + */ + @Test + @DisabledOnOs(OS.WINDOWS) + public void testNewZipWithQuestionMark() throws Exception { + final Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir")); + final Path zipPath = Paths.get(tmpDir.toString(), "ziputils?test-" + System.currentTimeMillis() + ".jar"); + try { + try (final FileSystem fs = ZipUtils.newZip(zipPath)) { + final Path someFileInZip = fs.getPath("hello.txt"); + Files.write(someFileInZip, "hello".getBytes(StandardCharsets.UTF_8)); + } + // now just verify that the content was actually written out + try (final FileSystem fs = ZipUtils.newFileSystem(zipPath)) { + assertFileExistsWithContent(fs.getPath("hello.txt"), "hello"); + } + } finally { + Files.deleteIfExists(zipPath); + } + } + /** * Tests that the {@link ZipUtils#newZip(Path)} works correctly, and creates the zip file, * when the parent directories of the {@link Path} passed to it are not present.