< prev index next >
src/java.base/share/classes/java/util/zip/ZipInputStream.java
Print this page
@@ -57,10 +57,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) {
@@ -111,17 +113,30 @@
* @return the next ZIP file entry, or null if there are no more entries
* @exception ZipException if a ZIP file error has occurred
* @exception IOException if an I/O error has occurred
*/
public ZipEntry getNextEntry() throws IOException {
+ return getNextEntry(null);
+ }
+
+ /**
+ * Reads the next ZIP file entry and positions the stream at the
+ * beginning of the entry data.
+ * @param zipCryption ZIP encrypt/decrypt engine. zip decryption will not
+ * work if this value set to null.
+ * @return the next ZIP file entry, or null if there are no more entries
+ * @exception ZipException if a ZIP file error has occurred
+ * @exception IOException if an I/O error has occurred
+ */
+ public ZipEntry getNextEntry(ZipCryption zipCryption) throws IOException {
ensureOpen();
if (entry != null) {
closeEntry();
}
crc.reset();
inf.reset();
- if ((entry = readLOC()) == null) {
+ if ((entry = readLOC(zipCryption)) == null) {
return null;
}
if (entry.method == STORED) {
remaining = entry.size;
}
@@ -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) +
@@ -271,20 +289,22 @@
private byte[] b = new byte[256];
/*
* Reads local file (LOC) header for next entry.
*/
- private ZipEntry readLOC() throws IOException {
+ private ZipEntry readLOC(ZipCryption zipCryption) throws IOException {
+ this.zipCryption = zipCryption;
+
try {
readFully(tmpbuf, 0, LOCHDR);
} catch (EOFException e) {
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,13 +316,14 @@
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");
+ if (((flag & 1) == 1) && (zipCryption == null)) {
+ throw new ZipException("ZipCryption is required.");
}
e.method = get16(tmpbuf, LOCHOW);
e.xdostime = get32(tmpbuf, LOCTIM);
if ((flag & 8) == 8) {
/* "Data Descriptor" present */
@@ -320,10 +341,26 @@
byte[] extra = new byte[len];
readFully(extra, 0, len);
e.setExtra0(extra,
e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL);
}
+
+ if (zipCryption != null) {
+ zipCryption.reset();
+ super.setZipCryption(zipCryption);
+
+ byte[] encryptionHeader =
+ new byte[zipCryption.getEncryptionHeaderSize()];
+ readFully(encryptionHeader, 0, encryptionHeader.length);
+ zipCryption.decryptBytes(encryptionHeader);
+
+ if (!zipCryption.isValid(e, encryptionHeader)) {
+ throw new ZipException("possibly incorrect passphrase");
+ }
+
+ }
+
return e;
}
/**
* Creates a new <code>ZipEntry</code> object for the specified
@@ -353,11 +390,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 +432,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 >