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