< prev index next >
src/java.base/share/classes/java/util/zip/ZipOutputStream.java
Print this page
*** 79,94 ****
private boolean closed = false;
private final ZipCoder zc;
! private static int version(ZipEntry e) throws ZipException {
switch (e.method) {
! case DEFLATED: return 20;
! case STORED: return 10;
! default: throw new ZipException("unsupported compression method");
}
}
/**
* Checks to make sure that this stream has not been closed.
*/
--- 79,116 ----
private boolean closed = false;
private final ZipCoder zc;
! private ZipCryption zipCryption;
!
! private int version(ZipEntry e) throws ZipException {
! int result;
!
switch (e.method) {
! case DEFLATED:
! result = 20;
! break;
!
! case STORED:
! result = 10;
! break;
!
! default:
! throw new ZipException("unsupported compression method");
}
+
+ /*
+ * Zip Crypto is defined version 2.0 or later.
+ * 4.4.3.2 Current minimum feature versions
+ * https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
+ */
+ if (zipCryption != null) {
+ result = 20;
+ }
+
+ return result;
}
/**
* Checks to make sure that this stream has not been closed.
*/
*** 165,176 ****
}
this.method = method;
}
/**
- * Sets the compression level for subsequent entries which are DEFLATED.
* The default setting is DEFAULT_COMPRESSION.
* @param level the compression level (0-9)
* @exception IllegalArgumentException if the compression level is invalid
*/
public void setLevel(int level) {
def.setLevel(level);
--- 187,198 ----
}
this.method = method;
}
/**
* The default setting is DEFAULT_COMPRESSION.
+ * Sets the compression level for subsequent entries which are DEFLATED.
* @param level the compression level (0-9)
* @exception IllegalArgumentException if the compression level is invalid
*/
public void setLevel(int level) {
def.setLevel(level);
*** 189,198 ****
--- 211,225 ----
public void putNextEntry(ZipEntry e) throws IOException {
ensureOpen();
if (current != null) {
closeEntry(); // close previous entry
}
+ zipCryption = e.zipCryption;
+ super.setZipCryption(zipCryption);
+ if (zipCryption != null) {
+ zipCryption.reset();
+ }
if (e.xdostime == -1) {
// by default, do NOT use extended timestamps in extra
// data, for now.
e.setTime(System.currentTimeMillis());
}
*** 222,243 ****
--- 249,281 ----
}
if (e.size == -1 || e.crc == -1) {
throw new ZipException(
"STORED entry missing size, compressed size, or crc-32");
}
+ if (zipCryption != null) {
+ e.csize += zipCryption.getEncryptionHeaderSize();
+ }
break;
default:
throw new ZipException("unsupported compression method");
}
if (! names.add(e.name)) {
throw new ZipException("duplicate entry: " + e.name);
}
if (zc.isUTF8())
e.flag |= EFS;
+ if (zipCryption != null)
+ e.flag |= 1; // Bit 0: If set, indicates that the file is encrypted.
current = new XEntry(e, written);
xentries.add(current);
writeLOC(current);
+
+ if (zipCryption != null) {
+ byte[] encryptionHeader = zipCryption.getEncryptionHeader(e);
+ writeBytes(encryptionHeader, 0, encryptionHeader.length);
+ locoff += encryptionHeader.length;
+ }
}
/**
* Closes the current ZIP entry and positions the stream for writing
* the next entry.
*** 278,287 ****
--- 316,334 ----
e.crc = crc.getValue();
writeEXT(e);
}
def.reset();
written += e.csize;
+
+ if (zipCryption != null) {
+ /* Substruct sizeof encryption header.
+ * This value adds in writeBytes() when encryption header
+ * is written.
+ */
+ written -= zipCryption.getEncryptionHeaderSize();
+ }
+
break;
case STORED:
// we already know that both e.size and e.csize are the same
if (e.size != written - locoff) {
throw new ZipException(
*** 327,349 ****
}
ZipEntry entry = current.entry;
switch (entry.method) {
case DEFLATED:
super.write(b, off, len);
break;
case STORED:
written += len;
if (written - locoff > entry.size) {
throw new ZipException(
"attempt to write past end of STORED entry");
}
out.write(b, off, len);
break;
default:
throw new ZipException("invalid compression method");
}
- crc.update(b, off, len);
}
/**
* Finishes writing the contents of the ZIP output stream without closing
* the underlying stream. Use this method when applying multiple filters
--- 374,403 ----
}
ZipEntry entry = current.entry;
switch (entry.method) {
case DEFLATED:
super.write(b, off, len);
+ crc.update(b, off, len);
break;
case STORED:
written += len;
if (written - locoff > entry.size) {
throw new ZipException(
"attempt to write past end of STORED entry");
}
+
+ crc.update(b, off, len);
+
+ if (zipCryption != null) {
+ zipCryption.encryptBytes(b, off, len);
+ }
+
out.write(b, off, len);
break;
default:
throw new ZipException("invalid compression method");
}
}
/**
* Finishes writing the contents of the ZIP output stream without closing
* the underlying stream. Use this method when applying multiple filters
*** 465,474 ****
--- 519,533 ----
* Writes extra data descriptor (EXT) for specified entry.
*/
private void writeEXT(ZipEntry e) throws IOException {
writeInt(EXTSIG); // EXT header signature
writeInt(e.crc); // crc-32
+
+ if (zipCryption != null) {
+ e.csize += zipCryption.getEncryptionHeaderSize();
+ }
+
if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) {
writeLong(e.csize);
writeLong(e.size);
} else {
writeInt(e.csize); // compressed size
< prev index next >