private void CopyThroughWithRecompute(Stream outstream) { int n; byte[] bytes = new byte[BufferSize]; var input = new CountingStream(this.ArchiveStream); long origRelativeOffsetOfHeader = _RelativeOffsetOfLocalHeader; // The header length may change due to rename of file, add a comment, etc. // We need to retain the original. int origLengthOfHeader = LengthOfHeader; // including crypto bytes! // WriteHeader() has the side effect of changing _RelativeOffsetOfLocalHeader // and setting _LengthOfHeader. While ReadHeader() reads the crypto header if // present, WriteHeader() does not write the crypto header. WriteHeader(outstream, 0); StoreRelativeOffset(); if (!this.FileName.EndsWith("/")) { // Not a directory; there is file data. // Seek to the beginning of the entry data in the input stream. long pos = origRelativeOffsetOfHeader + origLengthOfHeader; int len = GetLengthOfCryptoHeaderBytes(_Encryption_FromZipFile); pos -= len; // want to keep the crypto header _LengthOfHeader += len; input.Seek(pos, SeekOrigin.Begin); // copy through everything after the header to the output stream long remaining = this._CompressedSize; while (remaining > 0) { len = (remaining > bytes.Length) ? bytes.Length : (int)remaining; // read n = input.Read(bytes, 0, len); //_CheckRead(n); // write outstream.Write(bytes, 0, n); remaining -= n; OnWriteBlock(input.BytesRead, this._CompressedSize); if (_ioOperationCanceled) break; } // bit 3 descriptor if ((this._BitField & 0x0008) == 0x0008) { int size = 16; if (_InputUsesZip64) size += 8; byte[] Descriptor = new byte[size]; input.Read(Descriptor, 0, size); if (_InputUsesZip64 && _container.UseZip64WhenSaving == Zip64Option.Never) { // original descriptor was 24 bytes, now we need 16. // Must check for underflow here. // signature + CRC. outstream.Write(Descriptor, 0, 8); // Compressed if (_CompressedSize > 0xFFFFFFFF) throw new InvalidOperationException("ZIP64 is required"); outstream.Write(Descriptor, 8, 4); // UnCompressed if (_UncompressedSize > 0xFFFFFFFF) throw new InvalidOperationException("ZIP64 is required"); outstream.Write(Descriptor, 16, 4); _LengthOfTrailer -= 8; } else if (!_InputUsesZip64 && _container.UseZip64WhenSaving == Zip64Option.Always) { // original descriptor was 16 bytes, now we need 24 // signature + CRC byte[] pad = new byte[4]; outstream.Write(Descriptor, 0, 8); // Compressed outstream.Write(Descriptor, 8, 4); outstream.Write(pad, 0, 4); // UnCompressed outstream.Write(Descriptor, 12, 4); outstream.Write(pad, 0, 4); _LengthOfTrailer += 8; } else { // same descriptor on input and output. Copy it through. outstream.Write(Descriptor, 0, size); //_LengthOfTrailer += size; } } } _TotalEntrySize = _LengthOfHeader + _CompressedFileDataSize + _LengthOfTrailer; }
private void CopyThroughWithNoChange(Stream outstream) { int n; byte[] bytes = new byte[BufferSize]; var input = new CountingStream(this.ArchiveStream); // seek to the beginning of the entry data in the input stream input.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin); if (this._TotalEntrySize == 0) { // We've never set the length of the entry. // Set it here. this._TotalEntrySize = this._LengthOfHeader + this._CompressedFileDataSize + _LengthOfTrailer; // The CompressedSize includes all the leading metadata associated // to encryption, if any, as well as the compressed data, or // compressed-then-encrypted data, and the trailer in case of AES. // The CompressedFileData size is the same, less the encryption // framing data (12 bytes header for PKZip; 10/18 bytes header and // 10 byte trailer for AES). // The _LengthOfHeader includes all the zip entry header plus the // crypto header, if any. The _LengthOfTrailer includes the // 10-byte MAC for AES, where appropriate, and the bit-3 // Descriptor, where applicable. } // workitem 5616 // remember the offset, within the output stream, of this particular entry header. // This may have changed if any of the other entries changed (eg, if a different // entry was removed or added.) var counter = outstream as CountingStream; _RelativeOffsetOfLocalHeader = (counter != null) ? counter.ComputedPosition : outstream.Position; // BytesWritten // copy through the header, filedata, trailer, everything... long remaining = this._TotalEntrySize; while (remaining > 0) { int len = (remaining > bytes.Length) ? bytes.Length : (int)remaining; // read n = input.Read(bytes, 0, len); //_CheckRead(n); // write outstream.Write(bytes, 0, n); remaining -= n; OnWriteBlock(input.BytesRead, this._TotalEntrySize); if (_ioOperationCanceled) break; } }