< prev index next >
src/java.base/share/classes/java/util/zip/ZipFile.java
Print this page
@@ -321,11 +321,37 @@
* @throws ZipException if a ZIP format error has occurred
* @throws IOException if an I/O error has occurred
* @throws IllegalStateException if the zip file has been closed
*/
public InputStream getInputStream(ZipEntry entry) throws IOException {
+ return getInputStream(entry, null);
+ }
+
+ /**
+ * Returns an input stream for reading the contents of the specified
+ * zip file entry.
+ * <p>
+ * Closing this ZIP file will, in turn, close all input streams that
+ * have been returned by invocations of this method.
+ *
+ * @param entry the zip file entry
+ * @param zipCryption instance of ZipCryption
+ * @return the input stream for reading the contents of the specified
+ * zip file entry.
+ * @throws ZipException if a ZIP format error has occurred
+ * @throws IOException if an I/O error has occurred
+ * @throws IllegalStateException if the zip file has been closed
+ */
+ public InputStream getInputStream(ZipEntry entry, ZipCryption zipCryption)
+ throws IOException {
Objects.requireNonNull(entry, "entry");
+
+ if ((entry.flag & 1) == 1) {
+ Objects.requireNonNull(entry, "Passphrase is required");
+ zipCryption.reset();
+ }
+
int pos = -1;
ZipFileInputStream in = null;
synchronized (this) {
ensureOpen();
if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
@@ -334,13 +360,23 @@
pos = zsrc.getEntryPos(zc.getBytes(entry.name), false);
}
if (pos == -1) {
return null;
}
- in = new ZipFileInputStream(zsrc.cen, pos);
+ in = new ZipFileInputStream(zsrc.cen, pos, zipCryption);
switch (CENHOW(zsrc.cen, pos)) {
case STORED:
+ if((entry.flag & 1) == 1) {
+ byte[] encryptionHeader =
+ new byte[zipCryption.getEncryptionHeaderSize()];
+ in.readRaw(encryptionHeader, 0, encryptionHeader.length);
+ zipCryption.decryptBytes(encryptionHeader);
+
+ if (!zipCryption.isValid(entry, encryptionHeader)) {
+ throw new ZipException("possibly incorrect passphrase");
+ }
+ }
synchronized (streams) {
streams.put(in, null);
}
return in;
case DEFLATED:
@@ -352,10 +388,22 @@
}
if (size <= 0) {
size = 4096;
}
Inflater inf = getInflater();
+
+ if((entry.flag & 1) == 1) {
+ byte[] encryptionHeader =
+ new byte[zipCryption.getEncryptionHeaderSize()];
+ in.readRaw(encryptionHeader, 0, encryptionHeader.length);
+ zipCryption.decryptBytes(encryptionHeader);
+
+ if (!zipCryption.isValid(entry, encryptionHeader)) {
+ throw new ZipException("possibly incorrect passphrase");
+ }
+ }
+
InputStream is = new ZipFileInflaterInputStream(in, inf, (int)size);
synchronized (streams) {
streams.put(is, inf);
}
return is;
@@ -655,22 +703,25 @@
private class ZipFileInputStream extends InputStream {
private volatile boolean closeRequested = false;
private long pos; // current position within entry data
protected long rem; // number of remaining bytes within entry
protected long size; // uncompressed size of this entry
+ private ZipCryption zipCryption; // ZIP encrypt/decrypt engine
- ZipFileInputStream(byte[] cen, int cenpos) throws IOException {
+ ZipFileInputStream(byte[] cen, int cenpos, ZipCryption zipCryption)
+ throws IOException {
rem = CENSIZ(cen, cenpos);
size = CENLEN(cen, cenpos);
pos = CENOFF(cen, cenpos);
// zip64
if (rem == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL ||
pos == ZIP64_MAGICVAL) {
checkZIP64(cen, cenpos);
}
// negative for lazy initialization, see getDataOffset();
pos = - (pos + ZipFile.this.zsrc.locpos);
+ this.zipCryption = zipCryption;
}
private void checkZIP64(byte[] cen, int cenpos) throws IOException {
int off = cenpos + CENHDR + CENNAM(cen, cenpos);
int end = off + CENEXT(cen, cenpos);
@@ -728,10 +779,20 @@
}
return pos;
}
public int read(byte b[], int off, int len) throws IOException {
+ len = readRaw(b, off, len);
+
+ if (zipCryption != null) {
+ zipCryption.decryptBytes(b, off, len);
+ }
+
+ return len;
+ }
+
+ public int readRaw(byte b[], int off, int len) throws IOException {
synchronized (ZipFile.this) {
ensureOpenOrZipException();
initDataOffset();
if (rem == 0) {
return -1;
@@ -1177,12 +1238,10 @@
zerror("invalid CEN header (bad signature)");
int method = CENHOW(cen, pos);
int nlen = CENNAM(cen, pos);
int elen = CENEXT(cen, pos);
int clen = CENCOM(cen, pos);
- if ((CENFLG(cen, pos) & 1) != 0)
- zerror("invalid CEN header (encrypted entry)");
if (method != STORED && method != DEFLATED)
zerror("invalid CEN header (bad compression method: " + method + ")");
if (pos + CENHDR + nlen > limit)
zerror("invalid CEN header (bad header size)");
// Record the CEN offset and the name hash in our hash cell.
< prev index next >