~ubuntu-branches/debian/stretch/libcommons-compress-java/stretch

« back to all changes in this revision

Viewing changes to src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg
  • Date: 2015-08-31 23:22:38 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20150831232238-gz3ynyvs68tok1a3
Tags: 1.10-1
* New upstream release
* Updated the OSGi metadata

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 */
18
18
package org.apache.commons.compress.archivers.zip;
19
19
 
 
20
import java.io.ByteArrayOutputStream;
20
21
import java.io.File;
21
22
import java.io.FileOutputStream;
22
23
import java.io.IOException;
 
24
import java.io.InputStream;
23
25
import java.io.OutputStream;
24
26
import java.io.RandomAccessFile;
25
27
import java.nio.ByteBuffer;
 
28
import java.util.Calendar;
26
29
import java.util.HashMap;
27
30
import java.util.LinkedList;
28
31
import java.util.List;
29
32
import java.util.Map;
30
 
import java.util.zip.CRC32;
31
33
import java.util.zip.Deflater;
32
34
import java.util.zip.ZipException;
33
35
 
43
45
import static org.apache.commons.compress.archivers.zip.ZipConstants.ZIP64_MAGIC;
44
46
import static org.apache.commons.compress.archivers.zip.ZipConstants.ZIP64_MAGIC_SHORT;
45
47
import static org.apache.commons.compress.archivers.zip.ZipConstants.ZIP64_MIN_VERSION;
 
48
import static org.apache.commons.compress.archivers.zip.ZipLong.putLong;
 
49
import static org.apache.commons.compress.archivers.zip.ZipShort.putShort;
46
50
 
47
51
/**
48
52
 * Reimplementation of {@link java.util.zip.ZipOutputStream
75
79
public class ZipArchiveOutputStream extends ArchiveOutputStream {
76
80
 
77
81
    static final int BUFFER_SIZE = 512;
 
82
    private static final int LFH_SIG_OFFSET = 0;
 
83
    private static final int LFH_VERSION_NEEDED_OFFSET = 4;
 
84
    private static final int LFH_GPB_OFFSET = 6;
 
85
    private static final int LFH_METHOD_OFFSET = 8;
 
86
    private static final int LFH_TIME_OFFSET = 10;
 
87
    private static final int LFH_CRC_OFFSET = 14;
 
88
    private static final int LFH_COMPRESSED_SIZE_OFFSET = 18;
 
89
    private static final int LFH_ORIGINAL_SIZE_OFFSET = 22;
 
90
    private static final int LFH_FILENAME_LENGTH_OFFSET = 26;
 
91
    private static final int LFH_EXTRA_LENGTH_OFFSET = 28;
 
92
    private static final int LFH_FILENAME_OFFSET = 30;
 
93
    private static final int CFH_SIG_OFFSET = 0;
 
94
    private static final int CFH_VERSION_MADE_BY_OFFSET = 4;
 
95
    private static final int CFH_VERSION_NEEDED_OFFSET = 6;
 
96
    private static final int CFH_GPB_OFFSET = 8;
 
97
    private static final int CFH_METHOD_OFFSET = 10;
 
98
    private static final int CFH_TIME_OFFSET = 12;
 
99
    private static final int CFH_CRC_OFFSET = 16;
 
100
    private static final int CFH_COMPRESSED_SIZE_OFFSET = 20;
 
101
    private static final int CFH_ORIGINAL_SIZE_OFFSET = 24;
 
102
    private static final int CFH_FILENAME_LENGTH_OFFSET = 28;
 
103
    private static final int CFH_EXTRA_LENGTH_OFFSET = 30;
 
104
    private static final int CFH_COMMENT_LENGTH_OFFSET = 32;
 
105
    private static final int CFH_DISK_NUMBER_OFFSET = 34;
 
106
    private static final int CFH_INTERNAL_ATTRIBUTES_OFFSET = 36;
 
107
    private static final int CFH_EXTERNAL_ATTRIBUTES_OFFSET = 38;
 
108
    private static final int CFH_LFH_OFFSET = 42;
 
109
    private static final int CFH_FILENAME_OFFSET = 46;
78
110
 
79
111
    /** indicates if this archive is finished. protected for use in Jar implementation */
80
112
    protected boolean finished = false;
150
182
    private final List<ZipArchiveEntry> entries =
151
183
        new LinkedList<ZipArchiveEntry>();
152
184
 
153
 
    /**
154
 
     * CRC instance to avoid parsing DEFLATED data twice.
155
 
     */
156
 
    private final CRC32 crc = new CRC32();
157
 
 
158
 
    /**
159
 
     * Count the bytes written to out.
160
 
     */
161
 
    private long written = 0;
 
185
    private final StreamCompressor streamCompressor;
162
186
 
163
187
    /**
164
188
     * Start of central directory.
180
204
     */
181
205
    private static final byte[] LZERO = {0, 0, 0, 0};
182
206
 
 
207
    private static final byte[] ONE = ZipLong.getBytes(1L);
 
208
 
183
209
    /**
184
210
     * Holds the offsets of the LFH starts for each entry.
185
211
     */
204
230
    private ZipEncoding zipEncoding =
205
231
        ZipEncodingHelper.getZipEncoding(DEFAULT_ENCODING);
206
232
 
 
233
 
207
234
    /**
208
235
     * This Deflater object is used for output.
209
236
     *
210
237
     */
211
 
    protected final Deflater def = new Deflater(level, true);
212
 
 
213
 
    /**
214
 
     * This buffer serves as a Deflater.
215
 
     *
216
 
     */
217
 
    private final byte[] buf = new byte[BUFFER_SIZE];
218
 
 
 
238
    protected final Deflater def;
219
239
    /**
220
240
     * Optional random access output.
221
241
     */
248
268
 
249
269
    private Zip64Mode zip64Mode = Zip64Mode.AsNeeded;
250
270
 
 
271
    private final byte[] copyBuffer = new byte[32768];
 
272
    private final Calendar calendarInstance = Calendar.getInstance();
 
273
 
251
274
    /**
252
275
     * Creates a new ZIP OutputStream filtering the underlying stream.
253
276
     * @param out the outputstream to zip
255
278
    public ZipArchiveOutputStream(OutputStream out) {
256
279
        this.out = out;
257
280
        this.raf = null;
 
281
        def = new Deflater(level, true);
 
282
        streamCompressor = StreamCompressor.create(out, def);
258
283
    }
259
284
 
260
285
    /**
274
299
            _raf = null;
275
300
            o = new FileOutputStream(file);
276
301
        }
 
302
        def = new Deflater(level, true);
 
303
        streamCompressor = StreamCompressor.create(_raf, def);
277
304
        out = o;
278
305
        raf = _raf;
279
306
    }
322
349
     * encoding is UTF-8.
323
350
     *
324
351
     * <p>Defaults to true.</p>
 
352
     *
 
353
     * @param b whether to set the language encoding flag if the file
 
354
     * name encoding is UTF-8
325
355
     */
326
356
    public void setUseLanguageEncodingFlag(boolean b) {
327
357
        useUTF8Flag = b && ZipEncodingHelper.isUTF8(encoding);
331
361
     * Whether to create Unicode Extra Fields.
332
362
     *
333
363
     * <p>Defaults to NEVER.</p>
 
364
     *
 
365
     * @param b whether to create Unicode Extra Fields.
334
366
     */
335
367
    public void setCreateUnicodeExtraFields(UnicodeExtraFieldPolicy b) {
336
368
        createUnicodeExtraFields = b;
341
373
     * the file name cannot be encoded using the specified encoding.
342
374
     *
343
375
     * <p>Defaults to false.</p>
 
376
     *
 
377
     * @param b whether to fall back to UTF and the language encoding
 
378
     * flag if the file name cannot be encoded using the specified
 
379
     * encoding.
344
380
     */
345
381
    public void setFallbackToUTF8(boolean b) {
346
382
        fallbackToUTF8 = b;
389
425
     * case the default is {@link Zip64Mode#Never Never}.</p>
390
426
     *
391
427
     * @since 1.3
 
428
     * @param mode Whether Zip64 extensions will be used.
392
429
     */
393
430
    public void setUseZip64(Zip64Mode mode) {
394
431
        zip64Mode = mode;
410
447
            throw new IOException("This archive contains unclosed entries.");
411
448
        }
412
449
 
413
 
        cdOffset = written;
414
 
        for (ZipArchiveEntry ze : entries) {
415
 
            writeCentralFileHeader(ze);
416
 
        }
417
 
        cdLength = written - cdOffset;
 
450
        cdOffset = streamCompressor.getTotalBytesWritten();
 
451
        writeCentralDirectoryInChunks();
 
452
 
 
453
        cdLength = streamCompressor.getTotalBytesWritten() - cdOffset;
418
454
        writeZip64CentralDirectory();
419
455
        writeCentralDirectoryEnd();
420
456
        offsets.clear();
421
457
        entries.clear();
422
 
        def.end();
 
458
        streamCompressor.close();
423
459
        finished = true;
424
460
    }
425
461
 
 
462
    private void writeCentralDirectoryInChunks() throws IOException {
 
463
        int NUM_PER_WRITE = 1000;
 
464
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(70 * NUM_PER_WRITE);
 
465
        int count = 0;
 
466
        for (ZipArchiveEntry ze : entries) {
 
467
            byteArrayOutputStream.write(createCentralFileHeader(ze));
 
468
            if (++count > NUM_PER_WRITE){
 
469
                writeCounted(byteArrayOutputStream.toByteArray());
 
470
                byteArrayOutputStream.reset();
 
471
                count = 0;
 
472
            }
 
473
        }
 
474
        writeCounted(byteArrayOutputStream.toByteArray());
 
475
    }
 
476
 
426
477
    /**
427
478
     * Writes all necessary data for this entry.
428
479
     * @throws IOException on error
432
483
     */
433
484
    @Override
434
485
    public void closeArchiveEntry() throws IOException {
435
 
        if (finished) {
436
 
            throw new IOException("Stream has already been finished");
437
 
        }
438
 
 
439
 
        if (entry == null) {
440
 
            throw new IOException("No current entry to close");
441
 
        }
442
 
 
443
 
        if (!entry.hasWritten) {
444
 
            write(EMPTY, 0, 0);
445
 
        }
 
486
        preClose();
446
487
 
447
488
        flushDeflater();
448
489
 
 
490
        long bytesWritten = streamCompressor.getTotalBytesWritten() - entry.dataStart;
 
491
        long realCrc = streamCompressor.getCrc32();
 
492
        entry.bytesRead = streamCompressor.getBytesRead();
449
493
        final Zip64Mode effectiveMode = getEffectiveZip64Mode(entry.entry);
450
 
        long bytesWritten = written - entry.dataStart;
451
 
        long realCrc = crc.getValue();
452
 
        crc.reset();
453
 
 
454
 
        final boolean actuallyNeedsZip64 =
455
 
            handleSizesAndCrc(bytesWritten, realCrc, effectiveMode);
456
 
 
457
 
        if (raf != null) {
 
494
        final boolean actuallyNeedsZip64 = handleSizesAndCrc(bytesWritten, realCrc, effectiveMode);
 
495
        closeEntry(actuallyNeedsZip64, false);
 
496
        streamCompressor.reset();
 
497
    }
 
498
 
 
499
    /**
 
500
     * Writes all necessary data for this entry.
 
501
     *
 
502
     * @throws IOException            on error
 
503
     * @throws Zip64RequiredException if the entry's uncompressed or
 
504
     *                                compressed size exceeds 4 GByte and {@link #setUseZip64}
 
505
     *                                is {@link Zip64Mode#Never}.
 
506
     * @param phased              This entry is second phase of a 2-phase zip creation, size, compressed size and crc
 
507
     *                            are known in ZipArchiveEntry
 
508
     */
 
509
    private void closeCopiedEntry(boolean phased) throws IOException {
 
510
        preClose();
 
511
        entry.bytesRead = entry.entry.getSize();
 
512
        Zip64Mode effectiveMode = getEffectiveZip64Mode(entry.entry);
 
513
        boolean actuallyNeedsZip64 = checkIfNeedsZip64(effectiveMode);
 
514
        closeEntry(actuallyNeedsZip64, phased);
 
515
    }
 
516
 
 
517
    private void closeEntry(boolean actuallyNeedsZip64, boolean phased) throws IOException {
 
518
        if (!phased && raf != null) {
458
519
            rewriteSizesAndCrc(actuallyNeedsZip64);
459
520
        }
460
521
 
462
523
        entry = null;
463
524
    }
464
525
 
 
526
    private void preClose() throws IOException {
 
527
        if (finished) {
 
528
            throw new IOException("Stream has already been finished");
 
529
        }
 
530
 
 
531
        if (entry == null) {
 
532
            throw new IOException("No current entry to close");
 
533
        }
 
534
 
 
535
        if (!entry.hasWritten) {
 
536
            write(EMPTY, 0, 0);
 
537
        }
 
538
    }
 
539
 
 
540
    /**
 
541
     * Adds an archive entry with a raw input stream.
 
542
     *
 
543
     * If crc, size and compressed size are supplied on the entry, these values will be used as-is.
 
544
     * Zip64 status is re-established based on the settings in this stream, and the supplied value
 
545
     * is ignored.
 
546
     *
 
547
     * The entry is put and closed immediately.
 
548
     *
 
549
     * @param entry The archive entry to add
 
550
     * @param rawStream The raw input stream of a different entry. May be compressed/encrypted.
 
551
     * @throws IOException If copying fails
 
552
     */
 
553
    public void addRawArchiveEntry(ZipArchiveEntry entry, InputStream rawStream)
 
554
            throws IOException {
 
555
        ZipArchiveEntry ae = new ZipArchiveEntry(entry);
 
556
        if (hasZip64Extra(ae)) {
 
557
            // Will be re-added as required. this may make the file generated with this method
 
558
            // somewhat smaller than standard mode,
 
559
            // since standard mode is unable to remove the zip 64 header.
 
560
            ae.removeExtraField(Zip64ExtendedInformationExtraField.HEADER_ID);
 
561
        }
 
562
        boolean is2PhaseSource = ae.getCrc() != ZipArchiveEntry.CRC_UNKNOWN
 
563
                && ae.getSize() != ArchiveEntry.SIZE_UNKNOWN
 
564
                && ae.getCompressedSize() != ArchiveEntry.SIZE_UNKNOWN;
 
565
        putArchiveEntry(ae, is2PhaseSource);
 
566
        copyFromZipInputStream(rawStream);
 
567
        closeCopiedEntry(is2PhaseSource);
 
568
    }
 
569
 
465
570
    /**
466
571
     * Ensures all bytes sent to the deflater are written to the stream.
467
572
     */
468
573
    private void flushDeflater() throws IOException {
469
574
        if (entry.entry.getMethod() == DEFLATED) {
470
 
            def.finish();
471
 
            while (!def.finished()) {
472
 
                deflate();
473
 
            }
 
575
            streamCompressor.flushDeflater();
474
576
        }
475
577
    }
476
578
 
492
594
            entry.entry.setCompressedSize(bytesWritten);
493
595
            entry.entry.setCrc(crc);
494
596
 
495
 
            def.reset();
496
597
        } else if (raf == null) {
497
598
            if (entry.entry.getCrc() != crc) {
498
599
                throw new ZipException("bad CRC checksum for entry "
515
616
            entry.entry.setCrc(crc);
516
617
        }
517
618
 
518
 
        final boolean actuallyNeedsZip64 = effectiveMode == Zip64Mode.Always
519
 
            || entry.entry.getSize() >= ZIP64_MAGIC
520
 
            || entry.entry.getCompressedSize() >= ZIP64_MAGIC;
 
619
        return checkIfNeedsZip64(effectiveMode);
 
620
    }
 
621
 
 
622
    /**
 
623
     * Ensures the current entry's size and CRC information is set to
 
624
     * the values just written, verifies it isn't too big in the
 
625
     * Zip64Mode.Never case and returns whether the entry would
 
626
     * require a Zip64 extra field.
 
627
     */
 
628
    private boolean checkIfNeedsZip64(Zip64Mode effectiveMode)
 
629
            throws ZipException {
 
630
        final boolean actuallyNeedsZip64 = isZip64Required(entry.entry, effectiveMode);
521
631
        if (actuallyNeedsZip64 && effectiveMode == Zip64Mode.Never) {
522
 
            throw new Zip64RequiredException(Zip64RequiredException
523
 
                                             .getEntryTooBigMessage(entry.entry));
 
632
            throw new Zip64RequiredException(Zip64RequiredException.getEntryTooBigMessage(entry.entry));
524
633
        }
525
634
        return actuallyNeedsZip64;
526
635
    }
527
636
 
 
637
    private boolean isZip64Required(ZipArchiveEntry entry1, Zip64Mode requestedMode) {
 
638
        return requestedMode == Zip64Mode.Always || isTooLageForZip32(entry1);
 
639
    }
 
640
 
 
641
    private boolean isTooLageForZip32(ZipArchiveEntry zipArchiveEntry){
 
642
        return zipArchiveEntry.getSize() >= ZIP64_MAGIC || zipArchiveEntry.getCompressedSize() >= ZIP64_MAGIC;
 
643
    }
 
644
 
528
645
    /**
529
646
     * When using random access output, write the local file header
530
647
     * and potentiall the ZIP64 extra containing the correct CRC and
545
662
        }
546
663
 
547
664
        if (hasZip64Extra(entry.entry)) {
 
665
            ByteBuffer name = getName(entry.entry);
 
666
            int nameLen = name.limit() - name.position();
548
667
            // seek to ZIP64 extra, skip header and size information
549
668
            raf.seek(entry.localDataStart + 3 * WORD + 2 * SHORT
550
 
                     + getName(entry.entry).limit() + 2 * SHORT);
 
669
                     + nameLen + 2 * SHORT);
551
670
            // inside the ZIP64 extra uncompressed size comes
552
671
            // first, unlike the LFH, CD or data descriptor
553
672
            writeOut(ZipEightByteInteger.getBytes(entry.entry.getSize()));
584
703
     */
585
704
    @Override
586
705
    public void putArchiveEntry(ArchiveEntry archiveEntry) throws IOException {
 
706
        putArchiveEntry(archiveEntry, false);
 
707
    }
 
708
 
 
709
    /**
 
710
     * Writes the headers for an archive entry to the output stream.
 
711
     * The caller must then write the content to the stream and call
 
712
     * {@link #closeArchiveEntry()} to complete the process.
 
713
 
 
714
     * @param archiveEntry The archiveEntry
 
715
     * @param phased If true size, compressedSize and crc required to be known up-front in the archiveEntry
 
716
     * @throws ClassCastException if entry is not an instance of ZipArchiveEntry
 
717
     * @throws Zip64RequiredException if the entry's uncompressed or
 
718
     * compressed size is known to exceed 4 GByte and {@link #setUseZip64}
 
719
     * is {@link Zip64Mode#Never}.
 
720
     */
 
721
    private void putArchiveEntry(ArchiveEntry archiveEntry, boolean phased) throws IOException {
587
722
        if (finished) {
588
723
            throw new IOException("Stream has already been finished");
589
724
        }
607
742
            // just a placeholder, real data will be in data
608
743
            // descriptor or inserted later via RandomAccessFile
609
744
            ZipEightByteInteger size = ZipEightByteInteger.ZERO;
610
 
            if (entry.entry.getMethod() == STORED
611
 
                && entry.entry.getSize() != ArchiveEntry.SIZE_UNKNOWN) {
 
745
            ZipEightByteInteger compressedSize = ZipEightByteInteger.ZERO;
 
746
            if (phased){
 
747
                size = new ZipEightByteInteger(entry.entry.getSize());
 
748
                compressedSize = new ZipEightByteInteger(entry.entry.getCompressedSize());
 
749
            } else if (entry.entry.getMethod() == STORED
 
750
                    && entry.entry.getSize() != ArchiveEntry.SIZE_UNKNOWN) {
612
751
                // actually, we already know the sizes
613
752
                size = new ZipEightByteInteger(entry.entry.getSize());
 
753
                compressedSize = size;
614
754
            }
615
755
            z64.setSize(size);
616
 
            z64.setCompressedSize(size);
 
756
            z64.setCompressedSize(compressedSize);
617
757
            entry.entry.setExtra();
618
758
        }
619
759
 
621
761
            def.setLevel(level);
622
762
            hasCompressionLevelChanged = false;
623
763
        }
624
 
        writeLocalFileHeader(entry.entry);
 
764
        writeLocalFileHeader((ZipArchiveEntry) archiveEntry, phased);
625
765
    }
626
766
 
627
767
    /**
653
793
                                       + " STORED method when not writing to a"
654
794
                                       + " file");
655
795
            }
656
 
            if (entry.entry.getCrc() == -1) {
 
796
            if (entry.entry.getCrc() == ZipArchiveEntry.CRC_UNKNOWN) {
657
797
                throw new ZipException("crc checksum is required for STORED"
658
798
                                       + " method when not writing to a file");
659
799
            }
757
897
            throw new IllegalStateException("No current entry");
758
898
        }
759
899
        ZipUtil.checkRequestedFeatures(entry.entry);
 
900
        long writtenThisTime = streamCompressor.write(b, offset, length, entry.entry.getMethod());
 
901
        count(writtenThisTime);
 
902
    }
 
903
 
 
904
    /**
 
905
     * Write bytes to output or random access file.
 
906
     * @param data the byte array to write
 
907
     * @throws IOException on error
 
908
     */
 
909
    private void writeCounted(byte[] data) throws IOException {
 
910
        streamCompressor.writeCounted(data);
 
911
    }
 
912
 
 
913
    private void copyFromZipInputStream(InputStream src) throws IOException {
 
914
        if (entry == null) {
 
915
            throw new IllegalStateException("No current entry");
 
916
        }
 
917
        ZipUtil.checkRequestedFeatures(entry.entry);
760
918
        entry.hasWritten = true;
761
 
        if (entry.entry.getMethod() == DEFLATED) {
762
 
            writeDeflated(b, offset, length);
763
 
        } else {
764
 
            writeOut(b, offset, length);
765
 
            written += length;
766
 
        }
767
 
        crc.update(b, offset, length);
768
 
        count(length);
769
 
    }
770
 
 
771
 
    /**
772
 
     * write implementation for DEFLATED entries.
773
 
     */
774
 
    private void writeDeflated(byte[]b, int offset, int length)
775
 
        throws IOException {
776
 
        if (length > 0 && !def.finished()) {
777
 
            entry.bytesRead += length;
778
 
            if (length <= DEFLATER_BLOCK_SIZE) {
779
 
                def.setInput(b, offset, length);
780
 
                deflateUntilInputIsNeeded();
781
 
            } else {
782
 
                final int fullblocks = length / DEFLATER_BLOCK_SIZE;
783
 
                for (int i = 0; i < fullblocks; i++) {
784
 
                    def.setInput(b, offset + i * DEFLATER_BLOCK_SIZE,
785
 
                                 DEFLATER_BLOCK_SIZE);
786
 
                    deflateUntilInputIsNeeded();
787
 
                }
788
 
                final int done = fullblocks * DEFLATER_BLOCK_SIZE;
789
 
                if (done < length) {
790
 
                    def.setInput(b, offset + done, length - done);
791
 
                    deflateUntilInputIsNeeded();
792
 
                }
793
 
            }
 
919
        int length;
 
920
        while ((length = src.read(copyBuffer)) >= 0 )
 
921
        {
 
922
            streamCompressor.writeCounted(copyBuffer, 0, length);
 
923
            count( length );
794
924
        }
795
925
    }
796
926
 
857
987
     * @throws IOException on error
858
988
     */
859
989
    protected final void deflate() throws IOException {
860
 
        int len = def.deflate(buf, 0, buf.length);
861
 
        if (len > 0) {
862
 
            writeOut(buf, 0, len);
863
 
            written += len;
864
 
        }
 
990
        streamCompressor.deflate();
865
991
    }
866
992
 
867
993
    /**
870
996
     * @throws IOException on error
871
997
     */
872
998
    protected void writeLocalFileHeader(ZipArchiveEntry ze) throws IOException {
 
999
        writeLocalFileHeader(ze, false);
 
1000
    }
873
1001
 
 
1002
    private void writeLocalFileHeader(ZipArchiveEntry ze, boolean phased) throws IOException {
874
1003
        boolean encodable = zipEncoding.canEncode(ze.getName());
875
1004
        ByteBuffer name = getName(ze);
876
1005
 
878
1007
            addUnicodeExtraFields(ze, encodable, name);
879
1008
        }
880
1009
 
881
 
        offsets.put(ze, Long.valueOf(written));
882
 
 
883
 
        writeOut(LFH_SIG);
884
 
        written += WORD;
 
1010
        final byte[] localHeader = createLocalFileHeader(ze, name, encodable, phased);
 
1011
        long localHeaderStart = streamCompressor.getTotalBytesWritten();
 
1012
        offsets.put(ze, localHeaderStart);
 
1013
        entry.localDataStart = localHeaderStart + LFH_CRC_OFFSET; // At crc offset
 
1014
        writeCounted(localHeader);
 
1015
        entry.dataStart = streamCompressor.getTotalBytesWritten();
 
1016
    }
 
1017
 
 
1018
 
 
1019
    private byte[] createLocalFileHeader(ZipArchiveEntry ze, ByteBuffer name, boolean encodable,
 
1020
                                         boolean phased)  {
 
1021
        byte[] extra = ze.getLocalFileDataExtra();
 
1022
        final int nameLen = name.limit() - name.position();
 
1023
        int len= LFH_FILENAME_OFFSET + nameLen + extra.length;
 
1024
        byte[] buf = new byte[len];
 
1025
 
 
1026
        System.arraycopy(LFH_SIG,  0, buf, LFH_SIG_OFFSET, WORD);
885
1027
 
886
1028
        //store method in local variable to prevent multiple method calls
887
1029
        final int zipMethod = ze.getMethod();
888
1030
 
889
 
        writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod,
890
 
                                                         !encodable
891
 
                                                         && fallbackToUTF8,
892
 
                                                         hasZip64Extra(ze));
893
 
        written += WORD;
 
1031
        if (phased &&  !isZip64Required(entry.entry, zip64Mode)){
 
1032
            putShort(INITIAL_VERSION, buf, LFH_VERSION_NEEDED_OFFSET);
 
1033
        } else {
 
1034
            putShort(versionNeededToExtract(zipMethod, hasZip64Extra(ze)), buf, LFH_VERSION_NEEDED_OFFSET);
 
1035
        }
 
1036
 
 
1037
        GeneralPurposeBit generalPurposeBit = getGeneralPurposeBits(zipMethod, !encodable && fallbackToUTF8);
 
1038
        generalPurposeBit.encode(buf, LFH_GPB_OFFSET);
894
1039
 
895
1040
        // compression method
896
 
        writeOut(ZipShort.getBytes(zipMethod));
897
 
        written += SHORT;
 
1041
        putShort(zipMethod, buf, LFH_METHOD_OFFSET);
898
1042
 
899
 
        // last mod. time and date
900
 
        writeOut(ZipUtil.toDosTime(ze.getTime()));
901
 
        written += WORD;
 
1043
        ZipUtil.toDosTime(calendarInstance, ze.getTime(), buf, LFH_TIME_OFFSET);
902
1044
 
903
1045
        // CRC
 
1046
        if (phased){
 
1047
            putLong(ze.getCrc(), buf, LFH_CRC_OFFSET);
 
1048
        } else if (zipMethod == DEFLATED || raf != null) {
 
1049
            System.arraycopy(LZERO, 0, buf, LFH_CRC_OFFSET, WORD);
 
1050
        } else {
 
1051
            putLong(ze.getCrc(), buf, LFH_CRC_OFFSET);
 
1052
        }
 
1053
 
904
1054
        // compressed length
905
1055
        // uncompressed length
906
 
        entry.localDataStart = written;
907
 
        if (zipMethod == DEFLATED || raf != null) {
908
 
            writeOut(LZERO);
909
 
            if (hasZip64Extra(entry.entry)) {
910
 
                // point to ZIP64 extended information extra field for
911
 
                // sizes, may get rewritten once sizes are known if
912
 
                // stream is seekable
913
 
                writeOut(ZipLong.ZIP64_MAGIC.getBytes());
914
 
                writeOut(ZipLong.ZIP64_MAGIC.getBytes());
915
 
            } else {
916
 
                writeOut(LZERO);
917
 
                writeOut(LZERO);
918
 
            }
919
 
        } else {
920
 
            writeOut(ZipLong.getBytes(ze.getCrc()));
921
 
            byte[] size = ZipLong.ZIP64_MAGIC.getBytes();
922
 
            if (!hasZip64Extra(ze)) {
923
 
                size = ZipLong.getBytes(ze.getSize());
924
 
            }
925
 
            writeOut(size);
926
 
            writeOut(size);
 
1056
        if (hasZip64Extra(entry.entry)){
 
1057
            // point to ZIP64 extended information extra field for
 
1058
            // sizes, may get rewritten once sizes are known if
 
1059
            // stream is seekable
 
1060
            ZipLong.ZIP64_MAGIC.putLong(buf, LFH_COMPRESSED_SIZE_OFFSET);
 
1061
            ZipLong.ZIP64_MAGIC.putLong(buf, LFH_ORIGINAL_SIZE_OFFSET);
 
1062
        } else if (phased) {
 
1063
            putLong(ze.getCompressedSize(), buf, LFH_COMPRESSED_SIZE_OFFSET);
 
1064
            putLong(ze.getSize(), buf, LFH_ORIGINAL_SIZE_OFFSET);
 
1065
        } else if (zipMethod == DEFLATED || raf != null) {
 
1066
            System.arraycopy(LZERO, 0, buf, LFH_COMPRESSED_SIZE_OFFSET, WORD);
 
1067
            System.arraycopy(LZERO, 0, buf, LFH_ORIGINAL_SIZE_OFFSET, WORD);
 
1068
        } else { // Stored
 
1069
            putLong(ze.getSize(), buf, LFH_COMPRESSED_SIZE_OFFSET);
 
1070
            putLong(ze.getSize(), buf, LFH_ORIGINAL_SIZE_OFFSET);
927
1071
        }
928
 
        // CheckStyle:MagicNumber OFF
929
 
        written += 12;
930
 
        // CheckStyle:MagicNumber ON
931
 
 
932
1072
        // file name length
933
 
        writeOut(ZipShort.getBytes(name.limit()));
934
 
        written += SHORT;
 
1073
        putShort(nameLen, buf, LFH_FILENAME_LENGTH_OFFSET);
935
1074
 
936
1075
        // extra field length
937
 
        byte[] extra = ze.getLocalFileDataExtra();
938
 
        writeOut(ZipShort.getBytes(extra.length));
939
 
        written += SHORT;
 
1076
        putShort(extra.length, buf, LFH_EXTRA_LENGTH_OFFSET);
940
1077
 
941
1078
        // file name
942
 
        writeOut(name.array(), name.arrayOffset(),
943
 
                 name.limit() - name.position());
944
 
        written += name.limit();
945
 
 
946
 
        // extra field
947
 
        writeOut(extra);
948
 
        written += extra.length;
949
 
 
950
 
        entry.dataStart = written;
 
1079
        System.arraycopy( name.array(), name.arrayOffset(), buf, LFH_FILENAME_OFFSET, nameLen);
 
1080
 
 
1081
        System.arraycopy(extra, 0, buf, LFH_FILENAME_OFFSET + nameLen, extra.length);
 
1082
        return buf;
951
1083
    }
952
1084
 
 
1085
 
953
1086
    /**
954
1087
     * Adds UnicodeExtra fields for name and file comment if mode is
955
1088
     * ALWAYS or the data cannot be encoded using the configured
994
1127
        if (ze.getMethod() != DEFLATED || raf != null) {
995
1128
            return;
996
1129
        }
997
 
        writeOut(DD_SIG);
998
 
        writeOut(ZipLong.getBytes(ze.getCrc()));
999
 
        int sizeFieldSize = WORD;
 
1130
        writeCounted(DD_SIG);
 
1131
        writeCounted(ZipLong.getBytes(ze.getCrc()));
1000
1132
        if (!hasZip64Extra(ze)) {
1001
 
            writeOut(ZipLong.getBytes(ze.getCompressedSize()));
1002
 
            writeOut(ZipLong.getBytes(ze.getSize()));
 
1133
            writeCounted(ZipLong.getBytes(ze.getCompressedSize()));
 
1134
            writeCounted(ZipLong.getBytes(ze.getSize()));
1003
1135
        } else {
1004
 
            sizeFieldSize = DWORD;
1005
 
            writeOut(ZipEightByteInteger.getBytes(ze.getCompressedSize()));
1006
 
            writeOut(ZipEightByteInteger.getBytes(ze.getSize()));
 
1136
            writeCounted(ZipEightByteInteger.getBytes(ze.getCompressedSize()));
 
1137
            writeCounted(ZipEightByteInteger.getBytes(ze.getSize()));
1007
1138
        }
1008
 
        written += 2 * WORD + 2 * sizeFieldSize;
1009
1139
    }
1010
1140
 
1011
1141
    /**
1017
1147
     * Zip64Mode#Never}.
1018
1148
     */
1019
1149
    protected void writeCentralFileHeader(ZipArchiveEntry ze) throws IOException {
1020
 
        writeOut(CFH_SIG);
1021
 
        written += WORD;
1022
 
 
1023
 
        final long lfhOffset = offsets.get(ze).longValue();
 
1150
        byte[] centralFileHeader = createCentralFileHeader(ze);
 
1151
        writeCounted(centralFileHeader);
 
1152
    }
 
1153
 
 
1154
    private byte[] createCentralFileHeader(ZipArchiveEntry ze) throws IOException {
 
1155
 
 
1156
        final long lfhOffset = offsets.get(ze);
1024
1157
        final boolean needsZip64Extra = hasZip64Extra(ze)
1025
 
            || ze.getCompressedSize() >= ZIP64_MAGIC
1026
 
            || ze.getSize() >= ZIP64_MAGIC
1027
 
            || lfhOffset >= ZIP64_MAGIC;
 
1158
                || ze.getCompressedSize() >= ZIP64_MAGIC
 
1159
                || ze.getSize() >= ZIP64_MAGIC
 
1160
                || lfhOffset >= ZIP64_MAGIC;
1028
1161
 
1029
1162
        if (needsZip64Extra && zip64Mode == Zip64Mode.Never) {
1030
1163
            // must be the offset that is too big, otherwise an
1031
1164
            // exception would have been throw in putArchiveEntry or
1032
1165
            // closeArchiveEntry
1033
1166
            throw new Zip64RequiredException(Zip64RequiredException
1034
 
                                             .ARCHIVE_TOO_BIG_MESSAGE);
 
1167
                    .ARCHIVE_TOO_BIG_MESSAGE);
1035
1168
        }
1036
1169
 
 
1170
 
1037
1171
        handleZip64Extra(ze, lfhOffset, needsZip64Extra);
1038
1172
 
1039
 
        // version made by
1040
 
        // CheckStyle:MagicNumber OFF
1041
 
        writeOut(ZipShort.getBytes((ze.getPlatform() << 8) | 
1042
 
                                   (!hasUsedZip64 ? DATA_DESCRIPTOR_MIN_VERSION
1043
 
                                                  : ZIP64_MIN_VERSION)));
1044
 
        written += SHORT;
1045
 
 
1046
 
        final int zipMethod = ze.getMethod();
1047
 
        final boolean encodable = zipEncoding.canEncode(ze.getName());
1048
 
        writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod,
1049
 
                                                         !encodable
1050
 
                                                         && fallbackToUTF8,
1051
 
                                                         needsZip64Extra);
1052
 
        written += WORD;
1053
 
 
1054
 
        // compression method
1055
 
        writeOut(ZipShort.getBytes(zipMethod));
1056
 
        written += SHORT;
1057
 
 
1058
 
        // last mod. time and date
1059
 
        writeOut(ZipUtil.toDosTime(ze.getTime()));
1060
 
        written += WORD;
1061
 
 
1062
 
        // CRC
1063
 
        // compressed length
1064
 
        // uncompressed length
1065
 
        writeOut(ZipLong.getBytes(ze.getCrc()));
1066
 
        if (ze.getCompressedSize() >= ZIP64_MAGIC
1067
 
            || ze.getSize() >= ZIP64_MAGIC) {
1068
 
            writeOut(ZipLong.ZIP64_MAGIC.getBytes());
1069
 
            writeOut(ZipLong.ZIP64_MAGIC.getBytes());
1070
 
        } else {
1071
 
            writeOut(ZipLong.getBytes(ze.getCompressedSize()));
1072
 
            writeOut(ZipLong.getBytes(ze.getSize()));
1073
 
        }
1074
 
        // CheckStyle:MagicNumber OFF
1075
 
        written += 12;
1076
 
        // CheckStyle:MagicNumber ON
1077
 
 
1078
 
        ByteBuffer name = getName(ze);
1079
 
 
1080
 
        writeOut(ZipShort.getBytes(name.limit()));
1081
 
        written += SHORT;
1082
 
 
1083
 
        // extra field length
 
1173
        return createCentralFileHeader(ze, getName(ze), lfhOffset, needsZip64Extra);
 
1174
    }
 
1175
 
 
1176
    /**
 
1177
     * Writes the central file header entry.
 
1178
     * @param ze the entry to write
 
1179
     * @param name The encoded name
 
1180
     * @param lfhOffset Local file header offset for this file
 
1181
     * @throws IOException on error
 
1182
     */
 
1183
    private byte[] createCentralFileHeader(ZipArchiveEntry ze, ByteBuffer name, long lfhOffset,
 
1184
                                           boolean needsZip64Extra) throws IOException {
1084
1185
        byte[] extra = ze.getCentralDirectoryExtra();
1085
 
        writeOut(ZipShort.getBytes(extra.length));
1086
 
        written += SHORT;
1087
1186
 
1088
1187
        // file comment length
1089
1188
        String comm = ze.getComment();
1092
1191
        }
1093
1192
 
1094
1193
        ByteBuffer commentB = getEntryEncoding(ze).encode(comm);
1095
 
 
1096
 
        writeOut(ZipShort.getBytes(commentB.limit()));
1097
 
        written += SHORT;
 
1194
        final int nameLen = name.limit() - name.position();
 
1195
        final int commentLen = commentB.limit() - commentB.position();
 
1196
        int len= CFH_FILENAME_OFFSET + nameLen + extra.length + commentLen;
 
1197
        byte[] buf = new byte[len];
 
1198
 
 
1199
        System.arraycopy(CFH_SIG,  0, buf, CFH_SIG_OFFSET, WORD);
 
1200
 
 
1201
        // version made by
 
1202
        // CheckStyle:MagicNumber OFF
 
1203
        putShort((ze.getPlatform() << 8) | (!hasUsedZip64 ? DATA_DESCRIPTOR_MIN_VERSION : ZIP64_MIN_VERSION),
 
1204
                buf, CFH_VERSION_MADE_BY_OFFSET);
 
1205
 
 
1206
        final int zipMethod = ze.getMethod();
 
1207
        final boolean encodable = zipEncoding.canEncode(ze.getName());
 
1208
        putShort(versionNeededToExtract(zipMethod, needsZip64Extra), buf, CFH_VERSION_NEEDED_OFFSET);
 
1209
        getGeneralPurposeBits(zipMethod, !encodable && fallbackToUTF8).encode(buf, CFH_GPB_OFFSET);
 
1210
 
 
1211
        // compression method
 
1212
        putShort(zipMethod, buf, CFH_METHOD_OFFSET);
 
1213
 
 
1214
 
 
1215
        // last mod. time and date
 
1216
        ZipUtil.toDosTime(calendarInstance, ze.getTime(), buf, CFH_TIME_OFFSET);
 
1217
 
 
1218
        // CRC
 
1219
        // compressed length
 
1220
        // uncompressed length
 
1221
        putLong(ze.getCrc(), buf, CFH_CRC_OFFSET);
 
1222
        if (ze.getCompressedSize() >= ZIP64_MAGIC
 
1223
                || ze.getSize() >= ZIP64_MAGIC) {
 
1224
            ZipLong.ZIP64_MAGIC.putLong(buf, CFH_COMPRESSED_SIZE_OFFSET);
 
1225
            ZipLong.ZIP64_MAGIC.putLong(buf, CFH_ORIGINAL_SIZE_OFFSET);
 
1226
        } else {
 
1227
            putLong(ze.getCompressedSize(), buf, CFH_COMPRESSED_SIZE_OFFSET);
 
1228
            putLong(ze.getSize(), buf, CFH_ORIGINAL_SIZE_OFFSET);
 
1229
        }
 
1230
 
 
1231
        putShort(nameLen, buf, CFH_FILENAME_LENGTH_OFFSET);
 
1232
 
 
1233
        // extra field length
 
1234
        putShort(extra.length, buf, CFH_EXTRA_LENGTH_OFFSET);
 
1235
 
 
1236
        putShort(commentLen, buf, CFH_COMMENT_LENGTH_OFFSET);
1098
1237
 
1099
1238
        // disk number start
1100
 
        writeOut(ZERO);
1101
 
        written += SHORT;
 
1239
        System.arraycopy(ZERO, 0, buf, CFH_DISK_NUMBER_OFFSET, SHORT);
1102
1240
 
1103
1241
        // internal file attributes
1104
 
        writeOut(ZipShort.getBytes(ze.getInternalAttributes()));
1105
 
        written += SHORT;
 
1242
        putShort(ze.getInternalAttributes(), buf, CFH_INTERNAL_ATTRIBUTES_OFFSET);
1106
1243
 
1107
1244
        // external file attributes
1108
 
        writeOut(ZipLong.getBytes(ze.getExternalAttributes()));
1109
 
        written += WORD;
 
1245
        putLong(ze.getExternalAttributes(), buf, CFH_EXTERNAL_ATTRIBUTES_OFFSET);
1110
1246
 
1111
1247
        // relative offset of LFH
1112
 
        writeOut(ZipLong.getBytes(Math.min(lfhOffset, ZIP64_MAGIC)));
1113
 
        written += WORD;
 
1248
        putLong(Math.min(lfhOffset, ZIP64_MAGIC), buf, CFH_LFH_OFFSET);
1114
1249
 
1115
1250
        // file name
1116
 
        writeOut(name.array(), name.arrayOffset(),
1117
 
                 name.limit() - name.position());
1118
 
        written += name.limit();
1119
 
 
1120
 
        // extra field
1121
 
        writeOut(extra);
1122
 
        written += extra.length;
 
1251
        System.arraycopy(name.array(), name.arrayOffset(), buf, CFH_FILENAME_OFFSET, nameLen);
 
1252
 
 
1253
        int extraStart = CFH_FILENAME_OFFSET + nameLen;
 
1254
        System.arraycopy(extra, 0, buf, extraStart, extra.length);
 
1255
 
 
1256
        int commentStart = extraStart + extra.length;
1123
1257
 
1124
1258
        // file comment
1125
 
        writeOut(commentB.array(), commentB.arrayOffset(),
1126
 
                 commentB.limit() - commentB.position());
1127
 
        written += commentB.limit();
 
1259
        System.arraycopy(commentB.array(), commentB.arrayOffset(), buf, commentStart, commentLen);
 
1260
        return buf;
1128
1261
    }
1129
1262
 
1130
1263
    /**
1159
1292
     * and {@link Zip64Mode #setUseZip64} is {@link Zip64Mode#Never}.
1160
1293
     */
1161
1294
    protected void writeCentralDirectoryEnd() throws IOException {
1162
 
        writeOut(EOCD_SIG);
 
1295
        writeCounted(EOCD_SIG);
1163
1296
 
1164
1297
        // disk numbers
1165
 
        writeOut(ZERO);
1166
 
        writeOut(ZERO);
 
1298
        writeCounted(ZERO);
 
1299
        writeCounted(ZERO);
1167
1300
 
1168
1301
        // number of entries
1169
1302
        int numberOfEntries = entries.size();
1179
1312
 
1180
1313
        byte[] num = ZipShort.getBytes(Math.min(numberOfEntries,
1181
1314
                                                ZIP64_MAGIC_SHORT));
1182
 
        writeOut(num);
1183
 
        writeOut(num);
 
1315
        writeCounted(num);
 
1316
        writeCounted(num);
1184
1317
 
1185
1318
        // length and location of CD
1186
 
        writeOut(ZipLong.getBytes(Math.min(cdLength, ZIP64_MAGIC)));
1187
 
        writeOut(ZipLong.getBytes(Math.min(cdOffset, ZIP64_MAGIC)));
 
1319
        writeCounted(ZipLong.getBytes(Math.min(cdLength, ZIP64_MAGIC)));
 
1320
        writeCounted(ZipLong.getBytes(Math.min(cdOffset, ZIP64_MAGIC)));
1188
1321
 
1189
1322
        // ZIP file comment
1190
1323
        ByteBuffer data = this.zipEncoding.encode(comment);
1191
 
        writeOut(ZipShort.getBytes(data.limit()));
1192
 
        writeOut(data.array(), data.arrayOffset(),
1193
 
                 data.limit() - data.position());
 
1324
        int dataLen = data.limit() - data.position();
 
1325
        writeCounted(ZipShort.getBytes(dataLen));
 
1326
        streamCompressor.writeCounted(data.array(), data.arrayOffset(), dataLen);
1194
1327
    }
1195
1328
 
1196
 
    private static final byte[] ONE = ZipLong.getBytes(1L);
1197
 
 
1198
1329
    /**
1199
1330
     * Writes the &quot;ZIP64 End of central dir record&quot; and
1200
1331
     * &quot;ZIP64 End of central dir locator&quot;.
1217
1348
            return;
1218
1349
        }
1219
1350
 
1220
 
        long offset = written;
 
1351
        long offset = streamCompressor.getTotalBytesWritten();
1221
1352
 
1222
1353
        writeOut(ZIP64_EOCD_SIG);
1223
1354
        // size, we don't have any variable length as we don't support
1269
1400
     * @throws IOException on error
1270
1401
     */
1271
1402
    protected final void writeOut(byte[] data) throws IOException {
1272
 
        writeOut(data, 0, data.length);
 
1403
        streamCompressor.writeOut(data, 0, data.length);
1273
1404
    }
1274
1405
 
 
1406
 
1275
1407
    /**
1276
1408
     * Write bytes to output or random access file.
1277
1409
     * @param data the byte array to write
1280
1412
     * @throws IOException on error
1281
1413
     */
1282
1414
    protected final void writeOut(byte[] data, int offset, int length)
1283
 
        throws IOException {
1284
 
        if (raf != null) {
1285
 
            raf.write(data, offset, length);
1286
 
        } else {
1287
 
            out.write(data, offset, length);
1288
 
        }
1289
 
    }
1290
 
 
1291
 
    private void deflateUntilInputIsNeeded() throws IOException {
1292
 
        while (!def.needsInput()) {
1293
 
            deflate();
1294
 
        }
1295
 
    }
1296
 
 
1297
 
    private void writeVersionNeededToExtractAndGeneralPurposeBits(final int
1298
 
                                                                  zipMethod,
1299
 
                                                                  final boolean
1300
 
                                                                  utfFallback,
1301
 
                                                                  final boolean
1302
 
                                                                  zip64)
1303
 
        throws IOException {
1304
 
 
1305
 
        // CheckStyle:MagicNumber OFF
1306
 
        int versionNeededToExtract = INITIAL_VERSION;
 
1415
            throws IOException {
 
1416
        streamCompressor.writeOut(data, offset, length);
 
1417
    }
 
1418
 
 
1419
 
 
1420
    private GeneralPurposeBit getGeneralPurposeBits(final int zipMethod, final boolean utfFallback) {
1307
1421
        GeneralPurposeBit b = new GeneralPurposeBit();
1308
1422
        b.useUTF8ForNames(useUTF8Flag || utfFallback);
1309
 
        if (zipMethod == DEFLATED && raf == null) {
1310
 
            // requires version 2 as we are going to store length info
1311
 
            // in the data descriptor
1312
 
            versionNeededToExtract = DATA_DESCRIPTOR_MIN_VERSION;
 
1423
        if (isDeflatedToOutputStream(zipMethod)) {
1313
1424
            b.useDataDescriptor(true);
1314
1425
        }
 
1426
        return b;
 
1427
    }
 
1428
 
 
1429
    private int versionNeededToExtract(final int zipMethod, final boolean zip64) {
1315
1430
        if (zip64) {
1316
 
            versionNeededToExtract = ZIP64_MIN_VERSION;
 
1431
            return ZIP64_MIN_VERSION;
1317
1432
        }
1318
 
        // CheckStyle:MagicNumber ON
1319
 
 
1320
 
        // version needed to extract
1321
 
        writeOut(ZipShort.getBytes(versionNeededToExtract));
1322
 
        // general purpose bit flag
1323
 
        writeOut(b.encode());
1324
 
    }
 
1433
        // requires version 2 as we are going to store length info
 
1434
        // in the data descriptor
 
1435
        return (isDeflatedToOutputStream(zipMethod)) ?
 
1436
                DATA_DESCRIPTOR_MIN_VERSION :
 
1437
                INITIAL_VERSION;
 
1438
    }
 
1439
 
 
1440
    private boolean isDeflatedToOutputStream(int zipMethod) {
 
1441
        return zipMethod == DEFLATED && raf == null;
 
1442
    }
 
1443
 
1325
1444
 
1326
1445
    /**
1327
1446
     * Creates a new zip entry taking some information from the given