Use encoded version of path for jar URLs

Update `JarUrl` so that the encoded version of the path is used.
This allows jars to placed in directories with `#` or `!` in the
name.

Fixes gh-38660
This commit is contained in:
Phillip Webb 2023-12-06 15:57:50 -08:00
parent 847daf484c
commit 359a6cb5bb
3 changed files with 27 additions and 1 deletions

View File

@ -79,7 +79,7 @@ public final class JarUrl {
}
private static String getJarReference(File file, String nestedEntryName) {
String jarFilePath = file.toURI().getPath();
String jarFilePath = file.toURI().getRawPath().replace("!", "%21");
return (nestedEntryName != null) ? "nested:" + jarFilePath + "/!" + nestedEntryName : "file:" + jarFilePath;
}

View File

@ -512,6 +512,20 @@ class JarUrlConnectionTests {
}
}
@Test
void getJarFileWhenInFolderWithEncodedCharsReturnsJarFile() throws Exception {
this.temp = new File(this.temp, "te#st");
this.temp.mkdirs();
this.file = new File(this.temp, "test.jar");
this.url = JarUrl.create(this.file, "nested.jar");
assertThat(this.url.toString()).contains("te%23st");
TestJar.create(this.file);
JarUrlConnection connection = JarUrlConnection.open(this.url);
JarFile jarFile = connection.getJarFile();
assertThat(jarFile).isNotNull();
assertThat(jarFile.getEntry("3.dat")).isNotNull();
}
private long withoutNanos(long epochMilli) {
return Instant.ofEpochMilli(epochMilli).with(ChronoField.NANO_OF_SECOND, 0).toEpochMilli();
}

View File

@ -25,6 +25,8 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.boot.loader.net.util.UrlDecoder;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -84,4 +86,14 @@ class JarUrlTests {
assertThat(url).hasToString("jar:nested:%s/!lib.jar!/com/example/My.class".formatted(this.jarFileUrlPath));
}
@Test
void createWithReservedCharsInName() throws Exception {
String badFolderName = "foo#bar!/baz/!oof";
this.temp = new File(this.temp, badFolderName);
setup();
URL url = JarUrl.create(this.jarFile, "lib.jar", "com/example/My.class");
assertThat(url).hasToString("jar:nested:%s/!lib.jar!/com/example/My.class".formatted(this.jarFileUrlPath));
assertThat(UrlDecoder.decode(url.toString())).contains(badFolderName);
}
}