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