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:
Xueming Shen 2015-08-27 14:32:42 -07:00
parent c0889111a5
commit e6b269ec59
3 changed files with 87 additions and 5 deletions

View File

@ -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)

View File

@ -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();
}
}

View File

@ -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