/** * Writes bytes to ZIP entry. * @param b the byte array to write * @param offset the start position to write from * @param length the number of bytes to write * @throws IOException on error */ public override void write(byte[] b, int offset, int length) //throws IOException { ZipUtil.checkRequestedFeatures(entry); if (entry.getMethod() == DEFLATED) { if (length > 0) { if (!def.finished()) { if (length <= DEFLATER_BLOCK_SIZE) { def.setInput(b, offset, length); deflateUntilInputIsNeeded(); } else { int fullblocks = length / DEFLATER_BLOCK_SIZE; for (int i = 0; i < fullblocks; i++) { def.setInput(b, offset + i * DEFLATER_BLOCK_SIZE, DEFLATER_BLOCK_SIZE); deflateUntilInputIsNeeded(); } int done = fullblocks * DEFLATER_BLOCK_SIZE; if (done < length) { def.setInput(b, offset + done, length - done); deflateUntilInputIsNeeded(); } } } } } else { writeOut(b, offset, length); written += length; } crc.update(b, offset, length); count(length); }
/** * Set the extra field data in central directory. * @param data the data to use */ public virtual void setCentralDirectoryData(byte[] data) { centralData = ZipUtil.copy(data); }
/** * Get the local data. * @return the local data */ public virtual byte[] getLocalFileDataData() { return(ZipUtil.copy(localData)); }
/** * Set the extra field data in the local file data - * without Header-ID or length specifier. * @param data the field data to use */ public virtual void setLocalFileDataData(byte[] data) { localData = ZipUtil.copy(data); }
/** * Reads the central directory of the given archive and populates * the internal tables with ZipArchiveEntry instances. * * <p>The ZipArchiveEntrys will know all data that can be obtained from * the central directory alone, but not the data that requires the * local file header or additional data to be read.</p> * * @return a Map<ZipArchiveEntry, NameAndComment>> of * zipentries that didn't have the language encoding flag set when * read. */ private java.util.Map <ZipArchiveEntry, IAC_NameAndComment> populateFromCentralDirectory() //throws IOException { java.util.HashMap <ZipArchiveEntry, IAC_NameAndComment> noUTF8Flag = new java.util.HashMap <ZipArchiveEntry, IAC_NameAndComment>(); positionAtCentralDirectory(); byte[] cfh = new byte[CFH_LEN]; byte[] signatureBytes = new byte[WORD]; archive.readFully(signatureBytes); long sig = ZipLong.getValue(signatureBytes); long cfhSig = ZipLong.getValue(ZipArchiveOutputStream.CFH_SIG); if (sig != cfhSig && startsWithLocalFileHeader()) { throw new java.io.IOException("central directory is empty, can't expand" + " corrupt archive."); } while (sig == cfhSig) { archive.readFully(cfh); int off = 0; ZipArchiveEntry ze = new ZipArchiveEntry(); int versionMadeBy = ZipShort.getValue(cfh, off); off += SHORT; ze.setPlatform((versionMadeBy >> BYTE_SHIFT) & NIBLET_MASK); off += SHORT; // skip version info GeneralPurposeBit gpFlag = GeneralPurposeBit.parse(cfh, off); bool hasUTF8Flag = gpFlag.usesUTF8ForNames(); ZipEncoding entryEncoding = hasUTF8Flag ? ZipEncodingHelper.UTF8_ZIP_ENCODING : zipEncoding; ze.setGeneralPurposeBit(gpFlag); off += SHORT; ze.setMethod(ZipShort.getValue(cfh, off)); off += SHORT; // FIXME this is actually not very cpu cycles friendly as we are converting from // dos to java while the underlying Sun implementation will convert // from java to dos time for internal storage... long time = ZipUtil.dosToJavaTime(ZipLong.getValue(cfh, off)); ze.setTime(time); off += WORD; ze.setCrc(ZipLong.getValue(cfh, off)); off += WORD; ze.setCompressedSize(ZipLong.getValue(cfh, off)); off += WORD; ze.setSize(ZipLong.getValue(cfh, off)); off += WORD; int fileNameLen = ZipShort.getValue(cfh, off); off += SHORT; int extraLen = ZipShort.getValue(cfh, off); off += SHORT; int commentLen = ZipShort.getValue(cfh, off); off += SHORT; off += SHORT; // disk number ze.setInternalAttributes(ZipShort.getValue(cfh, off)); off += SHORT; ze.setExternalAttributes(ZipLong.getValue(cfh, off)); off += WORD; byte[] fileName = new byte[fileNameLen]; archive.readFully(fileName); ze.setName(entryEncoding.decode(fileName)); // LFH offset, IAC_OffsetEntry offset = new IAC_OffsetEntry(); offset.headerOffset = ZipLong.getValue(cfh, off); // data offset will be filled later entries.put(ze, offset); nameMap.put(ze.getName(), ze); byte[] cdExtraData = new byte[extraLen]; archive.readFully(cdExtraData); ze.setCentralDirectoryExtra(cdExtraData); byte[] comment = new byte[commentLen]; archive.readFully(comment); ze.setComment(entryEncoding.decode(comment)); archive.readFully(signatureBytes); sig = ZipLong.getValue(signatureBytes); if (!hasUTF8Flag && useUnicodeExtraFields) { noUTF8Flag.put(ze, new IAC_NameAndComment(fileName, comment)); } } return(noUTF8Flag); }
/** * Whether this class is able to read the given entry. * * <p>May return false if it is set up to use encryption or a * compression method that hasn't been implemented yet.</p> * @since Apache Commons Compress 1.1 */ public bool canReadEntryData(ZipArchiveEntry ze) { return(ZipUtil.canHandleEntryData(ze)); }
/** * Writes the central file header entry. * @param ze the entry to write * @throws IOException on error */ protected void writeCentralFileHeader(ZipArchiveEntry ze) //throws IOException { writeOut(CFH_SIG); written += WORD; // version made by // CheckStyle:MagicNumber OFF writeOut(ZipShort.getBytes((ze.getPlatform() << 8) | 20)); written += SHORT; int zipMethod = ze.getMethod(); bool encodable = zipEncoding.canEncode(ze.getName()); writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod, !encodable && fallbackToUTF8); 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())); writeOut(ZipLong.getBytes(ze.getCompressedSize())); writeOut(ZipLong.getBytes(ze.getSize())); // CheckStyle:MagicNumber OFF written += 12; // CheckStyle:MagicNumber ON // file name length ZipEncoding entryEncoding; if (!encodable && fallbackToUTF8) { entryEncoding = ZipEncodingHelper.UTF8_ZIP_ENCODING; } else { entryEncoding = zipEncoding; } java.nio.ByteBuffer name = entryEncoding.encode(ze.getName()); 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 = ""; } java.nio.ByteBuffer commentB = entryEncoding.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((byte[])offsets.get(ze)); written += WORD; // file name writeOut((byte[])name.array(), name.arrayOffset(), name.limit()); written += name.limit(); // extra field writeOut(extra); written += extra.Length; // file comment writeOut((byte[])commentB.array(), commentB.arrayOffset(), commentB.limit()); 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 { bool encodable = zipEncoding.canEncode(ze.getName()); ZipEncoding entryEncoding; if (!encodable && fallbackToUTF8) { entryEncoding = ZipEncodingHelper.UTF8_ZIP_ENCODING; } else { entryEncoding = zipEncoding; } java.nio.ByteBuffer name = entryEncoding.encode(ze.getName()); if (createUnicodeExtraFields != UnicodeExtraFieldPolicy.NEVER) { if (createUnicodeExtraFields == UnicodeExtraFieldPolicy.ALWAYS || !encodable) { ze.addExtraField(new UnicodePathExtraField(ze.getName(), (byte[])name.array(), name.arrayOffset(), name.limit())); } String comm = ze.getComment(); if (comm != null && !"".equals(comm)) { bool commentEncodable = this.zipEncoding.canEncode(comm); if (createUnicodeExtraFields == UnicodeExtraFieldPolicy.ALWAYS || !commentEncodable) { java.nio.ByteBuffer commentB = entryEncoding.encode(comm); ze.addExtraField(new UnicodeCommentExtraField(comm, (byte[])commentB.array(), commentB.arrayOffset(), commentB.limit()) ); } } } offsets.put(ze, ZipLong.getBytes(written)); writeOut(LFH_SIG); written += WORD; //store method in local variable to prevent multiple method calls int zipMethod = ze.getMethod(); writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod, !encodable && fallbackToUTF8); 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 localDataStart = written; if (zipMethod == DEFLATED || raf != null) { writeOut(LZERO); writeOut(LZERO); writeOut(LZERO); } else { writeOut(ZipLong.getBytes(ze.getCrc())); writeOut(ZipLong.getBytes(ze.getSize())); writeOut(ZipLong.getBytes(ze.getSize())); } // 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((byte[])name.array(), name.arrayOffset(), name.limit()); written += name.limit(); // extra field writeOut(extra); written += extra.Length; dataStart = written; }
/** * Writes all necessary data for this entry. * @throws IOException on error */ public override void closeArchiveEntry() //throws IOException { if (finished) { throw new java.io.IOException("Stream has already been finished"); } if (entry == null) { throw new java.io.IOException("No current entry to close"); } long realCrc = crc.getValue(); crc.reset(); if (entry.getMethod() == DEFLATED) { def.finish(); while (!def.finished()) { deflate(); } entry.setSize(ZipUtil.adjustToLong(def.getTotalIn())); entry.setCompressedSize(ZipUtil.adjustToLong(def.getTotalOut())); entry.setCrc(realCrc); def.reset(); written += entry.getCompressedSize(); } else if (raf == null) { if (entry.getCrc() != realCrc) { throw new java.util.zip.ZipException("bad CRC checksum for entry " + entry.getName() + ": " + java.lang.Long.toHexString(entry.getCrc()) + " instead of " + java.lang.Long.toHexString(realCrc)); } if (entry.getSize() != written - dataStart) { throw new java.util.zip.ZipException("bad size for entry " + entry.getName() + ": " + entry.getSize() + " instead of " + (written - dataStart)); } } else /* method is STORED and we used RandomAccessFile */ { long size = written - dataStart; entry.setSize(size); entry.setCompressedSize(size); entry.setCrc(realCrc); } // If random access output, write the local file header containing // the correct CRC and compressed/uncompressed sizes if (raf != null) { long save = raf.getFilePointer(); raf.seek(localDataStart); writeOut(ZipLong.getBytes(entry.getCrc())); writeOut(ZipLong.getBytes(entry.getCompressedSize())); writeOut(ZipLong.getBytes(entry.getSize())); raf.seek(save); } writeDataDescriptor(entry); entry = null; }
public override int read(byte[] buffer, int start, int length) //throws IOException { if (closed) { throw new java.io.IOException("The stream is closed"); } if (inf.finished() || current == null) { return(-1); } // avoid int overflow, check null buffer if (start <= buffer.Length && length >= 0 && start >= 0 && buffer.Length - start >= length) { ZipUtil.checkRequestedFeatures(current); if (!supportsDataDescriptorFor(current)) { throw new UnsupportedZipFeatureException(Feature.DATA_DESCRIPTOR, current); } if (current.getMethod() == ZipArchiveOutputStream.STORED) { if (hasDataDescriptor) { if (lastStoredEntry == null) { readStoredEntry(); } return(lastStoredEntry.read(buffer, start, length)); } int csize = (int)current.getSize(); if (readBytesOfEntry >= csize) { return(-1); } if (offsetInBuffer >= lengthOfLastRead) { offsetInBuffer = 0; if ((lengthOfLastRead = inJ.read(buf)) == -1) { return(-1); } count(lengthOfLastRead); bytesReadFromStream += lengthOfLastRead; } int toRead = length > lengthOfLastRead ? lengthOfLastRead - offsetInBuffer : length; if ((csize - readBytesOfEntry) < toRead) { toRead = csize - readBytesOfEntry; } java.lang.SystemJ.arraycopy(buf, offsetInBuffer, buffer, start, toRead); offsetInBuffer += toRead; readBytesOfEntry += toRead; crc.update(buffer, start, toRead); return(toRead); } if (inf.needsInput()) { fill(); if (lengthOfLastRead > 0) { bytesReadFromStream += lengthOfLastRead; } } int read = 0; try { read = inf.inflate(buffer, start, length); } catch (java.util.zip.DataFormatException e) { throw new java.util.zip.ZipException(e.getMessage()); } if (read == 0) { if (inf.finished()) { return(-1); } else if (lengthOfLastRead == -1) { throw new java.io.IOException("Truncated ZIP file"); } } crc.update(buffer, start, read); return(read); } throw new java.lang.ArrayIndexOutOfBoundsException(); }
public ZipArchiveEntry getNextZipEntry() //throws IOException { if (closed || hitCentralDirectory) { return(null); } if (current != null) { closeEntry(); } byte[] lfh = new byte[LFH_LEN]; try { readFully(lfh); } catch (java.io.EOFException) { return(null); } ZipLong sig = new ZipLong(lfh); if (sig.equals(ZipLong.CFH_SIG)) { hitCentralDirectory = true; return(null); } if (!sig.equals(ZipLong.LFH_SIG)) { return(null); } int off = WORD; current = new ZipArchiveEntry(); int versionMadeBy = ZipShort.getValue(lfh, off); off += SHORT; current.setPlatform((versionMadeBy >> ZipFile.BYTE_SHIFT) & ZipFile.NIBLET_MASK); GeneralPurposeBit gpFlag = GeneralPurposeBit.parse(lfh, off); bool hasUTF8Flag = gpFlag.usesUTF8ForNames(); ZipEncoding entryEncoding = hasUTF8Flag ? ZipEncodingHelper.UTF8_ZIP_ENCODING : zipEncoding; hasDataDescriptor = gpFlag.usesDataDescriptor(); current.setGeneralPurposeBit(gpFlag); off += SHORT; current.setMethod(ZipShort.getValue(lfh, off)); off += SHORT; long time = ZipUtil.dosToJavaTime(ZipLong.getValue(lfh, off)); current.setTime(time); off += WORD; if (!hasDataDescriptor) { current.setCrc(ZipLong.getValue(lfh, off)); off += WORD; current.setCompressedSize(ZipLong.getValue(lfh, off)); off += WORD; current.setSize(ZipLong.getValue(lfh, off)); off += WORD; } else { off += 3 * WORD; } int fileNameLen = ZipShort.getValue(lfh, off); off += SHORT; int extraLen = ZipShort.getValue(lfh, off); off += SHORT; byte[] fileName = new byte[fileNameLen]; readFully(fileName); current.setName(entryEncoding.decode(fileName)); byte[] extraData = new byte[extraLen]; readFully(extraData); current.setExtra(extraData); if (!hasUTF8Flag && useUnicodeExtraFields) { ZipUtil.setNameAndCommentFromExtraFields(current, fileName, null); } return(current); }
/** * The actual data to put into central directory. * * @return The CentralDirectoryData value */ public byte[] getCentralDirectoryData() { return(centralDirectoryData == null ? getLocalFileDataData() : ZipUtil.copy(centralDirectoryData)); }