示例#1
0
        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;
        }
示例#2
0
        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;
            }
        }