From 624a5f8260eaeda805e28e0f57c37c2819bf37f0 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 4 Apr 2018 14:07:55 -0700 Subject: [PATCH] Apply URL decoding for nested jar entry names Update `JarURLConnection` to apply URL decoding to nested jar entry names. Fixes gh-12765 --- .../boot/loader/jar/JarURLConnection.java | 6 +++--- .../boot/loader/TestJarCreator.java | 1 + .../boot/loader/archive/ExplodedArchiveTests.java | 2 +- .../boot/loader/archive/JarFileArchiveTests.java | 2 +- .../loader/jar/CentralDirectoryParserTests.java | 1 + .../boot/loader/jar/JarFileTests.java | 2 ++ .../boot/loader/jar/JarURLConnectionTests.java | 15 +++++++++++++++ 7 files changed, 24 insertions(+), 5 deletions(-) diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java index e44123cbfe..b45eb154f7 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java @@ -258,10 +258,10 @@ final class JarURLConnection extends java.net.JarURLConnection { int separator; int index = 0; while ((separator = spec.indexOf(SEPARATOR, index)) > 0) { - String entryName = spec.substring(index, separator); - JarEntry jarEntry = jarFile.getJarEntry(entryName); + JarEntryName entryName = JarEntryName.get(spec.substring(index, separator)); + JarEntry jarEntry = jarFile.getJarEntry(entryName.toString()); if (jarEntry == null) { - return JarURLConnection.notFound(jarFile, JarEntryName.get(entryName)); + return JarURLConnection.notFound(jarFile, entryName); } jarFile = jarFile.getNestedJarFile(jarEntry); index += separator + SEPARATOR.length(); diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java index a67fcb5795..2a1c8e288a 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java @@ -52,6 +52,7 @@ public abstract class TestJarCreator { writeNestedEntry("nested.jar", unpackNested, jarOutputStream); writeNestedEntry("another-nested.jar", unpackNested, jarOutputStream); + writeNestedEntry("space nested.jar", unpackNested, jarOutputStream); } finally { jarOutputStream.close(); diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/ExplodedArchiveTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/ExplodedArchiveTests.java index 3166ed3bd9..0676e7c2d3 100755 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/ExplodedArchiveTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/ExplodedArchiveTests.java @@ -108,7 +108,7 @@ public class ExplodedArchiveTests { @Test public void getEntries() throws Exception { Map entries = getEntriesMap(this.archive); - assertThat(entries.size()).isEqualTo(10); + assertThat(entries.size()).isEqualTo(11); } @Test diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/JarFileArchiveTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/JarFileArchiveTests.java index 7b555b6d7a..3ea5bb142e 100755 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/JarFileArchiveTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/JarFileArchiveTests.java @@ -82,7 +82,7 @@ public class JarFileArchiveTests { @Test public void getEntries() throws Exception { Map entries = getEntriesMap(this.archive); - assertThat(entries.size()).isEqualTo(10); + assertThat(entries.size()).isEqualTo(11); } @Test diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/CentralDirectoryParserTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/CentralDirectoryParserTests.java index 9a70d5e0b2..984655ecda 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/CentralDirectoryParserTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/CentralDirectoryParserTests.java @@ -90,6 +90,7 @@ public class CentralDirectoryParserTests { assertThat(headers.next().getName().toString()).isEqualTo("special/\u00EB.dat"); assertThat(headers.next().getName().toString()).isEqualTo("nested.jar"); assertThat(headers.next().getName().toString()).isEqualTo("another-nested.jar"); + assertThat(headers.next().getName().toString()).isEqualTo("space nested.jar"); assertThat(headers.hasNext()).isFalse(); } diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java index 6cff3ec742..6fe00ab615 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java @@ -93,6 +93,7 @@ public class JarFileTests { assertThat(entries.nextElement().getName()).isEqualTo("special/\u00EB.dat"); assertThat(entries.nextElement().getName()).isEqualTo("nested.jar"); assertThat(entries.nextElement().getName()).isEqualTo("another-nested.jar"); + assertThat(entries.nextElement().getName()).isEqualTo("space nested.jar"); assertThat(entries.hasMoreElements()).isFalse(); URL jarUrl = new URL("jar:" + this.rootJarFile.toURI() + "!/"); URLClassLoader urlClassLoader = new URLClassLoader(new URL[] { jarUrl }); @@ -135,6 +136,7 @@ public class JarFileTests { assertThat(entries.nextElement().getName()).isEqualTo("special/\u00EB.dat"); assertThat(entries.nextElement().getName()).isEqualTo("nested.jar"); assertThat(entries.nextElement().getName()).isEqualTo("another-nested.jar"); + assertThat(entries.nextElement().getName()).isEqualTo("space nested.jar"); assertThat(entries.hasMoreElements()).isFalse(); } diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java index ea73baf41e..1307976938 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarURLConnectionTests.java @@ -137,6 +137,21 @@ public class JarURLConnectionTests { .hasSameContentAs(new ByteArrayInputStream(new byte[] { 3 })); } + @Test + public void connectionToEntryWithSpaceNestedEntry() throws Exception { + URL url = new URL("jar:file:" + getRelativePath() + "!/space nested.jar!/3.dat"); + assertThat(JarURLConnection.get(url, this.jarFile).getInputStream()) + .hasSameContentAs(new ByteArrayInputStream(new byte[] { 3 })); + } + + @Test + public void connectionToEntryWithEncodedSpaceNestedEntry() throws Exception { + URL url = new URL( + "jar:file:" + getRelativePath() + "!/space%20nested.jar!/3.dat"); + assertThat(JarURLConnection.get(url, this.jarFile).getInputStream()) + .hasSameContentAs(new ByteArrayInputStream(new byte[] { 3 })); + } + @Test public void getContentLengthReturnsLengthOfUnderlyingEntry() throws Exception { URL url = new URL(new URL("jar", null, -1,