< prev index next >
src/java.base/share/classes/java/util/zip/ZipInputStream.java
Print this page
@@ -29,10 +29,11 @@
import java.io.IOException;
import java.io.EOFException;
import java.io.PushbackInputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.util.Objects;
import static java.util.zip.ZipConstants64.*;
import static java.util.zip.ZipUtils.*;
/**
* This class implements an input stream filter for reading files in the
@@ -57,10 +58,12 @@
// one entry
private boolean entryEOF = false;
private ZipCoder zc;
+ private ZipCryption zipCryption;
+
/**
* Check to make sure that this stream has not been closed
*/
private void ensureOpen() throws IOException {
if (closed) {
@@ -187,10 +190,22 @@
}
if (entry == null) {
return -1;
}
+
+ if (entry.isPassphraseRequired()) {
+ if (!entry.isValidPassphrase()) {
+ throw new ZipException("possibly incorrect passphrase");
+ }
+
+ zipCryption = entry.zipCryption;
+ super.setZipCryption(zipCryption);
+ } else {
+ zipCryption = null;
+ }
+
switch (entry.method) {
case DEFLATED:
len = super.read(b, off, len);
if (len == -1) {
readEnd(entry);
@@ -211,10 +226,13 @@
}
len = in.read(b, off, len);
if (len == -1) {
throw new ZipException("unexpected EOF");
}
+ if (zipCryption != null) {
+ zipCryption.decryptBytes(b, off, len);
+ }
crc.update(b, off, len);
remaining -= len;
if (remaining == 0 && entry.crc != crc.getValue()) {
throw new ZipException(
"invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
@@ -280,11 +298,11 @@
return null;
}
if (get32(tmpbuf, 0) != LOCSIG) {
return null;
}
- // get flag first, we need check EFS.
+ // get flag first, we need check EFS and encryption.
flag = get16(tmpbuf, LOCFLG);
// get the entry name and create the ZipEntry first
int len = get16(tmpbuf, LOCNAM);
int blen = b.length;
if (len > blen) {
@@ -296,14 +314,12 @@
readFully(b, 0, len);
// Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
ZipEntry e = createZipEntry(((flag & EFS) != 0)
? zc.toStringUTF8(b, len)
: zc.toString(b, len));
+ e.flag = flag;
// now get the remaining fields for the entry
- if ((flag & 1) == 1) {
- throw new ZipException("encrypted ZIP entry not supported");
- }
e.method = get16(tmpbuf, LOCHOW);
e.xdostime = get32(tmpbuf, LOCTIM);
if ((flag & 8) == 8) {
/* "Data Descriptor" present */
if (e.method != DEFLATED) {
@@ -320,10 +336,17 @@
byte[] extra = new byte[len];
readFully(extra, 0, len);
e.setExtra0(extra,
e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL);
}
+
+ if (e.isPassphraseRequired()) {
+ e.encryptionHeader =
+ new byte[TraditionalZipCryption.ENCRYPTION_HEADER_SIZE];
+ readFully(e.encryptionHeader, 0, e.encryptionHeader.length);
+ }
+
return e;
}
/**
* Creates a new <code>ZipEntry</code> object for the specified
@@ -353,11 +376,12 @@
* compatibility."""
*/
private void readEnd(ZipEntry e) throws IOException {
int n = inf.getRemaining();
if (n > 0) {
- ((PushbackInputStream)in).unread(buf, len - n, n);
+ ((PushbackInputStream)in).unread(
+ (zipCryption == null) ? buf : originBuf, len - n, n);
}
if ((flag & 8) == 8) {
/* "Data Descriptor" present */
if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
inf.getBytesRead() > ZIP64_MAGICVAL) {
@@ -394,10 +418,13 @@
if (e.size != inf.getBytesWritten()) {
throw new ZipException(
"invalid entry size (expected " + e.size +
" but got " + inf.getBytesWritten() + " bytes)");
}
+ if (zipCryption != null) {
+ e.csize -= zipCryption.getEncryptionHeaderSize();
+ }
if (e.csize != inf.getBytesRead()) {
throw new ZipException(
"invalid entry compressed size (expected " + e.csize +
" but got " + inf.getBytesRead() + " bytes)");
}
< prev index next >