8064601: Improve jar file handling
Reviewed-by: alanb, coffeys
This commit is contained in:
parent
31896469fd
commit
e7cf4064cc
jdk/src/jdk.jartool/share/classes/sun/tools/jar
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -74,8 +74,9 @@ class Main {
|
||||
* Mflag: DO NOT generate a manifest file (just ZIP)
|
||||
* iflag: generate jar index
|
||||
* nflag: Perform jar normalization at the end
|
||||
* pflag: preserve/don't strip leading slash and .. component from file name
|
||||
*/
|
||||
boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag;
|
||||
boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag;
|
||||
|
||||
static final String MANIFEST_DIR = "META-INF/";
|
||||
static final String VERSION = "1.0";
|
||||
@ -187,6 +188,7 @@ class Main {
|
||||
addMainClass(manifest, ename);
|
||||
}
|
||||
}
|
||||
expand(null, files, false);
|
||||
OutputStream out;
|
||||
if (fname != null) {
|
||||
out = new FileOutputStream(fname);
|
||||
@ -208,7 +210,6 @@ class Main {
|
||||
tmpfile = createTemporaryFile(tmpbase, ".jar");
|
||||
out = new FileOutputStream(tmpfile);
|
||||
}
|
||||
expand(null, files, false);
|
||||
create(new BufferedOutputStream(out, 4096), manifest);
|
||||
if (in != null) {
|
||||
in.close();
|
||||
@ -424,6 +425,9 @@ class Main {
|
||||
case 'e':
|
||||
ename = args[count++];
|
||||
break;
|
||||
case 'P':
|
||||
pflag = true;
|
||||
break;
|
||||
default:
|
||||
error(formatMsg("error.illegal.option",
|
||||
String.valueOf(flags.charAt(i))));
|
||||
@ -713,6 +717,47 @@ class Main {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final boolean isWinDriveLetter(char c) {
|
||||
return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
|
||||
}
|
||||
|
||||
private String safeName(String name) {
|
||||
if (!pflag) {
|
||||
int len = name.length();
|
||||
int i = name.lastIndexOf("../");
|
||||
if (i == -1) {
|
||||
i = 0;
|
||||
} else {
|
||||
i += 3; // strip any dot-dot components
|
||||
}
|
||||
if (File.separatorChar == '\\') {
|
||||
// the spec requests no drive letter. skip if
|
||||
// the entry name has one.
|
||||
while (i < len) {
|
||||
int off = i;
|
||||
if (i + 1 < len &&
|
||||
name.charAt(i + 1) == ':' &&
|
||||
isWinDriveLetter(name.charAt(i))) {
|
||||
i += 2;
|
||||
}
|
||||
while (i < len && name.charAt(i) == '/') {
|
||||
i++;
|
||||
}
|
||||
if (i == off) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (i < len && name.charAt(i) == '/') {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (i != 0) {
|
||||
name = name.substring(i);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private String entryName(String name) {
|
||||
name = name.replace(File.separatorChar, '/');
|
||||
@ -723,11 +768,10 @@ class Main {
|
||||
matchPath = path;
|
||||
}
|
||||
}
|
||||
name = name.substring(matchPath.length());
|
||||
|
||||
if (name.startsWith("/")) {
|
||||
name = name.substring(1);
|
||||
} else if (name.startsWith("./")) {
|
||||
name = safeName(name.substring(matchPath.length()));
|
||||
// the old implementaton doesn't remove
|
||||
// "./" if it was led by "/" (?)
|
||||
if (name.startsWith("./")) {
|
||||
name = name.substring(2);
|
||||
}
|
||||
return name;
|
||||
@ -927,8 +971,11 @@ class Main {
|
||||
for (ZipEntry ze : zes) {
|
||||
long lastModified = ze.getTime();
|
||||
if (lastModified != -1) {
|
||||
File f = new File(ze.getName().replace('/', File.separatorChar));
|
||||
f.setLastModified(lastModified);
|
||||
String name = safeName(ze.getName().replace(File.separatorChar, '/'));
|
||||
if (name.length() != 0) {
|
||||
File f = new File(name.replace('/', File.separatorChar));
|
||||
f.setLastModified(lastModified);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1002,8 +1049,16 @@ class Main {
|
||||
*/
|
||||
ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException {
|
||||
ZipEntry rc = null;
|
||||
String name = e.getName();
|
||||
File f = new File(e.getName().replace('/', File.separatorChar));
|
||||
// The spec requres all slashes MUST be forward '/', it is possible
|
||||
// an offending zip/jar entry may uses the backwards slash in its
|
||||
// name. It might cause problem on Windows platform as it skips
|
||||
// our "safe" check for leading slahs and dot-dot. So replace them
|
||||
// with '/'.
|
||||
String name = safeName(e.getName().replace(File.separatorChar, '/'));
|
||||
if (name.length() == 0) {
|
||||
return rc; // leading '/' or 'dot-dot' only path
|
||||
}
|
||||
File f = new File(name.replace('/', File.separatorChar));
|
||||
if (e.isDirectory()) {
|
||||
if (f.exists()) {
|
||||
if (!f.isDirectory()) {
|
||||
|
@ -68,7 +68,7 @@ out.size=\
|
||||
(in = {0}) (out= {1})
|
||||
|
||||
usage=\
|
||||
Usage: jar {ctxui}[vfmn0Me] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
|
||||
Usage: jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...\n\
|
||||
Options:\n\
|
||||
\ \ -c create new archive\n\
|
||||
\ \ -t list table of contents for archive\n\
|
||||
@ -81,6 +81,7 @@ Options:\n\
|
||||
\ \ -e specify application entry point for stand-alone application \n\
|
||||
\ \ bundled into an executable jar file\n\
|
||||
\ \ -0 store only; use no ZIP compression\n\
|
||||
\ \ -P preserve leading '/' (absolute path) and ".." (parent directory) components from file names\n\
|
||||
\ \ -M do not create a manifest file for the entries\n\
|
||||
\ \ -i generate index information for the specified jar files\n\
|
||||
\ \ -C change to the specified directory and include the following file\n\
|
||||
|
Loading…
x
Reference in New Issue
Block a user