8131067: (zipfs) Zip File System Provider returns doubly-encoded Path URIs
To decode the zip file path uri before passing it into zippath uri. Reviewed-by: alanb
This commit is contained in:
parent
c0889111a5
commit
e6b269ec59
@ -65,8 +65,9 @@ public class ZipFileSystemProvider extends FileSystemProvider {
|
||||
// only support legacy JAR URL syntax jar:{uri}!/{entry} for now
|
||||
String spec = uri.getRawSchemeSpecificPart();
|
||||
int sep = spec.indexOf("!/");
|
||||
if (sep != -1)
|
||||
if (sep != -1) {
|
||||
spec = spec.substring(0, sep);
|
||||
}
|
||||
return Paths.get(new URI(spec)).toAbsolutePath();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
@ -107,6 +108,9 @@ public class ZipFileSystemProvider extends FileSystemProvider {
|
||||
// assume NOT a zip/jar file
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (realPath == null) { // newly created
|
||||
realPath = path.toRealPath();
|
||||
}
|
||||
filesystems.put(realPath, zipfs);
|
||||
return zipfs;
|
||||
}
|
||||
@ -132,7 +136,6 @@ public class ZipFileSystemProvider extends FileSystemProvider {
|
||||
|
||||
@Override
|
||||
public Path getPath(URI uri) {
|
||||
|
||||
String spec = uri.getSchemeSpecificPart();
|
||||
int sep = spec.indexOf("!/");
|
||||
if (sep == -1)
|
||||
|
@ -32,10 +32,10 @@ import java.nio.file.*;
|
||||
import java.nio.file.DirectoryStream.Filter;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.util.*;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.nio.file.StandardOpenOption.*;
|
||||
import static java.nio.file.StandardCopyOption.*;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal
|
||||
@ -180,7 +180,7 @@ class ZipPath implements Path {
|
||||
public URI toUri() {
|
||||
try {
|
||||
return new URI("jar",
|
||||
zfs.getZipFile().toUri() +
|
||||
decodeUri(zfs.getZipFile().toUri().toString()) +
|
||||
"!" +
|
||||
zfs.getString(toAbsolutePath().path),
|
||||
null);
|
||||
@ -866,4 +866,57 @@ class ZipPath implements Path {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int decode(char c) {
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
return c - '0';
|
||||
if ((c >= 'a') && (c <= 'f'))
|
||||
return c - 'a' + 10;
|
||||
if ((c >= 'A') && (c <= 'F'))
|
||||
return c - 'A' + 10;
|
||||
assert false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// to avoid double escape
|
||||
static String decodeUri(String s) {
|
||||
if (s == null)
|
||||
return s;
|
||||
int n = s.length();
|
||||
if (n == 0)
|
||||
return s;
|
||||
if (s.indexOf('%') < 0)
|
||||
return s;
|
||||
|
||||
StringBuilder sb = new StringBuilder(n);
|
||||
byte[] bb = new byte[n];
|
||||
boolean betweenBrackets = false;
|
||||
|
||||
for (int i = 0; i < n;) {
|
||||
char c = s.charAt(i);
|
||||
if (c == '[') {
|
||||
betweenBrackets = true;
|
||||
} else if (betweenBrackets && c == ']') {
|
||||
betweenBrackets = false;
|
||||
}
|
||||
if (c != '%' || betweenBrackets ) {
|
||||
sb.append(c);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
int nb = 0;
|
||||
while (c == '%') {
|
||||
assert (n - i >= 2);
|
||||
bb[nb++] = (byte)(((decode(s.charAt(++i)) & 0xf) << 4) |
|
||||
(decode(s.charAt(++i)) & 0xf));
|
||||
if (++i >= n) {
|
||||
break;
|
||||
}
|
||||
c = s.charAt(i);
|
||||
}
|
||||
sb.append(new String(bb, 0, nb, UTF_8));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
@ -69,6 +70,7 @@ import static java.nio.file.StandardCopyOption.*;
|
||||
* @test
|
||||
* @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
|
||||
* 7157656 8002390 7012868 7012856 8015728 8038500 8040059 8069211
|
||||
* 8131067
|
||||
* @summary Test Zip filesystem provider
|
||||
* @run main ZipFSTester
|
||||
* @run main/othervm/java.security.policy=test.policy ZipFSTester
|
||||
@ -91,6 +93,7 @@ public class ZipFSTester {
|
||||
}
|
||||
testTime(jarFile);
|
||||
test8069211();
|
||||
test8131067();
|
||||
}
|
||||
|
||||
static void test0(FileSystem fs)
|
||||
@ -441,11 +444,34 @@ public class ZipFSTester {
|
||||
}
|
||||
}
|
||||
|
||||
static void test8131067() throws Exception {
|
||||
Map<String, Object> env = new HashMap<String, Object>();
|
||||
env.put("create", "true");
|
||||
|
||||
// file name with space character for URI to quote it
|
||||
File tmp = File.createTempFile("test zipfs", "zip");
|
||||
tmp.delete(); // we need a clean path, no file
|
||||
Path fsPath = tmp.toPath();
|
||||
try (FileSystem fs = newZipFileSystem(fsPath, env);) {
|
||||
Files.write(fs.getPath("/foo"), "hello".getBytes());
|
||||
URI fooUri = fs.getPath("/foo").toUri();
|
||||
if (!Arrays.equals(Files.readAllBytes(Paths.get(fooUri)),
|
||||
"hello".getBytes())) {
|
||||
throw new RuntimeException("entry close() failed");
|
||||
}
|
||||
} finally {
|
||||
Files.delete(fsPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
|
||||
throws Exception
|
||||
{
|
||||
// Use URLDecoder (for test only) to remove the double escaped space
|
||||
// character
|
||||
return FileSystems.newFileSystem(
|
||||
new URI("jar", path.toUri().toString(), null), env, null);
|
||||
new URI("jar", URLDecoder.decode(path.toUri().toString(), "utf8"),
|
||||
null), env, null);
|
||||
}
|
||||
|
||||
private static Path getTempPath() throws IOException
|
||||
|
Loading…
Reference in New Issue
Block a user