< 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.
*/
*** 114,124 ****
* to encode the entry names and comments.
*
* @param out the actual output stream
*/
public ZipOutputStream(OutputStream out) {
! this(out, StandardCharsets.UTF_8);
}
/**
* Creates a new ZIP output stream.
*
--- 136,159 ----
* to encode the entry names and comments.
*
* @param out the actual output stream
*/
public ZipOutputStream(OutputStream out) {
! this(out, StandardCharsets.UTF_8, null);
! }
!
! /**
! * Creates a new ZIP output stream.
! *
! * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used
! * to encode the entry names and comments.
! *
! * @param out the actual output stream
! * @param zipCryption ZIP encrypt/decrypt engine
! */
! public ZipOutputStream(OutputStream out, ZipCryption zipCryption) {
! this(out, StandardCharsets.UTF_8, zipCryption);
}
/**
* Creates a new ZIP output stream.
*
*** 128,142 ****
--- 163,194 ----
* to be used to encode the entry names and comments
*
* @since 1.7
*/
public ZipOutputStream(OutputStream out, Charset charset) {
+ this(out, charset, null);
+ }
+
+ /**
+ * Creates a new ZIP output stream.
+ *
+ * @param out the actual output stream
+ *
+ * @param charset the {@linkplain java.nio.charset.Charset charset}
+ * to be used to encode the entry names and comments
+ *
+ * @param zipCryption ZIP encrypt/decrypt engine
+ */
+ public ZipOutputStream(OutputStream out,
+ Charset charset, ZipCryption zipCryption) {
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
usesDefaultDeflater = true;
+ this.zipCryption = zipCryption;
+ super.setZipCryption(zipCryption);
}
/**
* Sets the ZIP file comment.
* @param comment the comment string
*** 189,198 ****
--- 241,253 ----
public void putNextEntry(ZipEntry e) throws IOException {
ensureOpen();
if (current != null) {
closeEntry(); // close previous entry
}
+ 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 ****
--- 277,309 ----
}
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 ****
--- 344,362 ----
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
--- 402,431 ----
}
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 ****
--- 547,561 ----
* 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 >