/** * Writes the central file header entry. * * @param ze the entry to write * @throws IOException on error * @throws Zip64RequiredException if the archive's size exceeds 4 GByte and {@link Zip64Mode * #setUseZip64} is {@link Zip64Mode#Never}. */ protected void writeCentralFileHeader(ZipArchiveEntry ze) throws IOException { writeOut(CFH_SIG); written += WORD; final long lfhOffset = offsets.get(ze).longValue(); final boolean needsZip64Extra = hasZip64Extra(ze) || ze.getCompressedSize() >= ZIP64_MAGIC || ze.getSize() >= ZIP64_MAGIC || lfhOffset >= ZIP64_MAGIC; if (needsZip64Extra && zip64Mode == Zip64Mode.Never) { // must be the offset that is too big, otherwise an // exception would have been throw in putArchiveEntry or // closeArchiveEntry throw new Zip64RequiredException(Zip64RequiredException.ARCHIVE_TOO_BIG_MESSAGE); } handleZip64Extra(ze, lfhOffset, needsZip64Extra); // version made by // CheckStyle:MagicNumber OFF writeOut( ZipShort.getBytes( (ze.getPlatform() << 8) | (!hasUsedZip64 ? DATA_DESCRIPTOR_MIN_VERSION : ZIP64_MIN_VERSION))); written += SHORT; final int zipMethod = ze.getMethod(); final boolean encodable = zipEncoding.canEncode(ze.getName()); writeVersionNeededToExtractAndGeneralPurposeBits( zipMethod, !encodable && fallbackToUTF8, needsZip64Extra); written += WORD; // compression method writeOut(ZipShort.getBytes(zipMethod)); written += SHORT; // last mod. time and date writeOut(ZipUtil.toDosTime(ze.getTime())); written += WORD; // CRC // compressed length // uncompressed length writeOut(ZipLong.getBytes(ze.getCrc())); if (ze.getCompressedSize() >= ZIP64_MAGIC || ze.getSize() >= ZIP64_MAGIC) { writeOut(ZipLong.ZIP64_MAGIC.getBytes()); writeOut(ZipLong.ZIP64_MAGIC.getBytes()); } else { writeOut(ZipLong.getBytes(ze.getCompressedSize())); writeOut(ZipLong.getBytes(ze.getSize())); } // CheckStyle:MagicNumber OFF written += 12; // CheckStyle:MagicNumber ON ByteBuffer name = getName(ze); writeOut(ZipShort.getBytes(name.limit())); written += SHORT; // extra field length byte[] extra = ze.getCentralDirectoryExtra(); writeOut(ZipShort.getBytes(extra.length)); written += SHORT; // file comment length String comm = ze.getComment(); if (comm == null) { comm = ""; } ByteBuffer commentB = getEntryEncoding(ze).encode(comm); writeOut(ZipShort.getBytes(commentB.limit())); written += SHORT; // disk number start writeOut(ZERO); written += SHORT; // internal file attributes writeOut(ZipShort.getBytes(ze.getInternalAttributes())); written += SHORT; // external file attributes writeOut(ZipLong.getBytes(ze.getExternalAttributes())); written += WORD; // relative offset of LFH writeOut(ZipLong.getBytes(Math.min(lfhOffset, ZIP64_MAGIC))); written += WORD; // file name writeOut(name.array(), name.arrayOffset(), name.limit() - name.position()); written += name.limit(); // extra field writeOut(extra); written += extra.length; // file comment writeOut(commentB.array(), commentB.arrayOffset(), commentB.limit() - commentB.position()); written += commentB.limit(); }
/** * Writes the local file header entry * * @param ze the entry to write * @throws IOException on error */ protected void writeLocalFileHeader(ZipArchiveEntry ze) throws IOException { boolean encodable = zipEncoding.canEncode(ze.getName()); ByteBuffer name = getName(ze); if (createUnicodeExtraFields != UnicodeExtraFieldPolicy.NEVER) { addUnicodeExtraFields(ze, encodable, name); } offsets.put(ze, Long.valueOf(written)); writeOut(LFH_SIG); written += WORD; // store method in local variable to prevent multiple method calls final int zipMethod = ze.getMethod(); writeVersionNeededToExtractAndGeneralPurposeBits( zipMethod, !encodable && fallbackToUTF8, hasZip64Extra(ze)); written += WORD; // compression method writeOut(ZipShort.getBytes(zipMethod)); written += SHORT; // last mod. time and date writeOut(ZipUtil.toDosTime(ze.getTime())); written += WORD; // CRC // compressed length // uncompressed length entry.localDataStart = written; if (zipMethod == DEFLATED || raf != null) { writeOut(LZERO); if (hasZip64Extra(entry.entry)) { // point to ZIP64 extended information extra field for // sizes, may get rewritten once sizes are known if // stream is seekable writeOut(ZipLong.ZIP64_MAGIC.getBytes()); writeOut(ZipLong.ZIP64_MAGIC.getBytes()); } else { writeOut(LZERO); writeOut(LZERO); } } else { writeOut(ZipLong.getBytes(ze.getCrc())); byte[] size = ZipLong.ZIP64_MAGIC.getBytes(); if (!hasZip64Extra(ze)) { size = ZipLong.getBytes(ze.getSize()); } writeOut(size); writeOut(size); } // CheckStyle:MagicNumber OFF written += 12; // CheckStyle:MagicNumber ON // file name length writeOut(ZipShort.getBytes(name.limit())); written += SHORT; // extra field length byte[] extra = ze.getLocalFileDataExtra(); writeOut(ZipShort.getBytes(extra.length)); written += SHORT; // file name writeOut(name.array(), name.arrayOffset(), name.limit() - name.position()); written += name.limit(); // extra field writeOut(extra); written += extra.length; entry.dataStart = written; }