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