Crisis.Ionic.Zip.ZipEntry.PostProcessOutput C# (CSharp) Метод

PostProcessOutput() приватный Метод

private PostProcessOutput ( Stream s ) : void
s Stream
Результат void
        internal void PostProcessOutput(Stream s)
        {
            var s1 = s as CountingStream;

            // workitem 8931 - for WriteDelegate.
            // The WriteDelegate changes things because there can be a zero-byte stream
            // written. In all other cases DotNetZip knows the length of the stream
            // before compressing and encrypting. In this case we have to circle back,
            // and omit all the crypto stuff - the GP bitfield, and the crypto header.
            if (_UncompressedSize == 0 && _CompressedSize == 0)
            {
                if (this._Source == ZipEntrySource.ZipOutputStream) return;  // nothing to do...

                if (_Password != null)
                {
                    int headerBytesToRetract = 0;
                    if (Encryption == EncryptionAlgorithm.PkzipWeak)
                        headerBytesToRetract = 12;
#if AESCRYPTO
                    else if (Encryption == EncryptionAlgorithm.WinZipAes128 ||
                             Encryption == EncryptionAlgorithm.WinZipAes256)
                    {
                        headerBytesToRetract = _aesCrypto_forWrite._Salt.Length + _aesCrypto_forWrite.GeneratedPV.Length;
                    }
#endif
                    if (this._Source == ZipEntrySource.ZipOutputStream && !s.CanSeek)
                        throw new ZipException("Zero bytes written, encryption in use, and non-seekable output.");

                    if (Encryption != EncryptionAlgorithm.None)
                    {
                        // seek back in the stream to un-output the security metadata
                        s.Seek(-1 * headerBytesToRetract, SeekOrigin.Current);
                        s.SetLength(s.Position);
                        // workitem 10178
                        Crisis.Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s);

                        // workitem 11131
                        // adjust the count on the CountingStream as necessary
                        if (s1 != null) s1.Adjust(headerBytesToRetract);

                        // subtract the size of the security header from the _LengthOfHeader
                        _LengthOfHeader -= headerBytesToRetract;
                        __FileDataPosition -= headerBytesToRetract;
                    }
                    _Password = null;

                    // turn off the encryption bit
                    _BitField &= ~(0x0001);

                    // copy the updated bitfield value into the header
                    int j = 6;
                    _EntryHeader[j++] = (byte)(_BitField & 0x00FF);
                    _EntryHeader[j++] = (byte)((_BitField & 0xFF00) >> 8);

#if AESCRYPTO
                    if (Encryption == EncryptionAlgorithm.WinZipAes128 ||
                        Encryption == EncryptionAlgorithm.WinZipAes256)
                    {
                        // Fix the extra field - overwrite the 0x9901 headerId
                        // with dummy data. (arbitrarily, 0x9999)
                        Int16 fnLength = (short)(_EntryHeader[26] + _EntryHeader[27] * 256);
                        int offx = 30 + fnLength;
                        int aesIndex = FindExtraFieldSegment(_EntryHeader, offx, 0x9901);
                        if (aesIndex >= 0)
                        {
                            _EntryHeader[aesIndex++] = 0x99;
                            _EntryHeader[aesIndex++] = 0x99;
                        }
                    }
#endif
                }

                CompressionMethod = 0;
                Encryption = EncryptionAlgorithm.None;
            }
            else if (_zipCrypto_forWrite != null
#if AESCRYPTO
                     || _aesCrypto_forWrite != null
#endif
                     )

            {
                if (Encryption == EncryptionAlgorithm.PkzipWeak)
                {
                    _CompressedSize += 12; // 12 extra bytes for the encryption header
                }
#if AESCRYPTO
                else if (Encryption == EncryptionAlgorithm.WinZipAes128 ||
                         Encryption == EncryptionAlgorithm.WinZipAes256)
                {
                    // adjust the compressed size to include the variable (salt+pv)
                    // security header and 10-byte trailer. According to the winzip AES
                    // spec, that metadata is included in the "Compressed Size" figure
                    // when encoding the zip archive.
                    _CompressedSize += _aesCrypto_forWrite.SizeOfEncryptionMetadata;
                }
#endif
            }

            int i = 8;
            _EntryHeader[i++] = (byte)(_CompressionMethod & 0x00FF);
            _EntryHeader[i++] = (byte)((_CompressionMethod & 0xFF00) >> 8);

            i = 14;
            // CRC - the correct value now
            _EntryHeader[i++] = (byte)(_Crc32 & 0x000000FF);
            _EntryHeader[i++] = (byte)((_Crc32 & 0x0000FF00) >> 8);
            _EntryHeader[i++] = (byte)((_Crc32 & 0x00FF0000) >> 16);
            _EntryHeader[i++] = (byte)((_Crc32 & 0xFF000000) >> 24);

            SetZip64Flags();

            // (i==26) filename length (Int16)
            Int16 filenameLength = (short)(_EntryHeader[26] + _EntryHeader[27] * 256);
            Int16 extraFieldLength = (short)(_EntryHeader[28] + _EntryHeader[29] * 256);

            if (_OutputUsesZip64.Value)
            {
                // VersionNeededToExtract - set to 45 to indicate zip64
                _EntryHeader[4] = (byte)(45 & 0x00FF);
                _EntryHeader[5] = 0x00;

                // workitem 7924 - don't need bit 3
                // // workitem 7917
                // // set bit 3 for ZIP64 compatibility with WinZip12
                // _BitField |= 0x0008;
                // _EntryHeader[6] = (byte)(_BitField & 0x00FF);

                // CompressedSize and UncompressedSize - 0xFF
                for (int j = 0; j < 8; j++)
                    _EntryHeader[i++] = 0xff;

                // At this point we need to find the "Extra field" that follows the
                // filename.  We had already emitted it, but the data (uncomp, comp,
                // ROLH) was not available at the time we did so.  Here, we emit it
                // again, with final values.

                i = 30 + filenameLength;
                _EntryHeader[i++] = 0x01;  // zip64
                _EntryHeader[i++] = 0x00;

                i += 2; // skip over data size, which is 16+4

                Array.Copy(BitConverter.GetBytes(_UncompressedSize), 0, _EntryHeader, i, 8);
                i += 8;
                Array.Copy(BitConverter.GetBytes(_CompressedSize), 0, _EntryHeader, i, 8);
            }
            else
            {
                // VersionNeededToExtract - reset to 20 since no zip64
                _EntryHeader[4] = (byte)(20 & 0x00FF);
                _EntryHeader[5] = 0x00;

                // CompressedSize - the correct value now
                i = 18;
                _EntryHeader[i++] = (byte)(_CompressedSize & 0x000000FF);
                _EntryHeader[i++] = (byte)((_CompressedSize & 0x0000FF00) >> 8);
                _EntryHeader[i++] = (byte)((_CompressedSize & 0x00FF0000) >> 16);
                _EntryHeader[i++] = (byte)((_CompressedSize & 0xFF000000) >> 24);

                // UncompressedSize - the correct value now
                _EntryHeader[i++] = (byte)(_UncompressedSize & 0x000000FF);
                _EntryHeader[i++] = (byte)((_UncompressedSize & 0x0000FF00) >> 8);
                _EntryHeader[i++] = (byte)((_UncompressedSize & 0x00FF0000) >> 16);
                _EntryHeader[i++] = (byte)((_UncompressedSize & 0xFF000000) >> 24);

                // The HeaderId in the extra field header, is already dummied out.
                if (extraFieldLength != 0)
                {
                    i = 30 + filenameLength;
                    // For zip archives written by this library, if the zip64
                    // header exists, it is the first header. Because of the logic
                    // used when first writing the _EntryHeader bytes, the
                    // HeaderId is not guaranteed to be any particular value.  So
                    // we determine if the first header is a putative zip64 header
                    // by examining the datasize.  UInt16 HeaderId =
                    // (UInt16)(_EntryHeader[i] + _EntryHeader[i + 1] * 256);
                    Int16 DataSize = (short)(_EntryHeader[i + 2] + _EntryHeader[i + 3] * 256);
                    if (DataSize == 16)
                    {
                        // reset to Header Id to dummy value, effectively dummy-ing out the zip64 metadata
                        _EntryHeader[i++] = 0x99;
                        _EntryHeader[i++] = 0x99;
                    }
                }
            }


#if AESCRYPTO

            if (Encryption == EncryptionAlgorithm.WinZipAes128 ||
                Encryption == EncryptionAlgorithm.WinZipAes256)
            {
                // Must set compressionmethod to 0x0063 (decimal 99)
                //
                // and then set the compression method bytes inside the extra
                // field to the actual compression method value.

                i = 8;
                _EntryHeader[i++] = 0x63;
                _EntryHeader[i++] = 0;

                i = 30 + filenameLength;
                do
                {
                    UInt16 HeaderId = (UInt16)(_EntryHeader[i] + _EntryHeader[i + 1] * 256);
                    Int16 DataSize = (short)(_EntryHeader[i + 2] + _EntryHeader[i + 3] * 256);
                    if (HeaderId != 0x9901)
                    {
                        // skip this header
                        i += DataSize + 4;
                    }
                    else
                    {
                        i += 9;
                        // actual compression method
                        _EntryHeader[i++] = (byte)(_CompressionMethod & 0x00FF);
                        _EntryHeader[i++] = (byte)(_CompressionMethod & 0xFF00);
                    }
                } while (i < (extraFieldLength - 30 - filenameLength));
            }
#endif

            // finally, write the data.

            // workitem 7216 - sometimes we don't seek even if we CAN.  ASP.NET
            // Response.OutputStream, or stdout are non-seekable.  But we may also want
            // to NOT seek in other cases, eg zip64.  For all cases, we just check bit 3
            // to see if we want to seek.  There's one exception - if using a
            // ZipOutputStream, and PKZip encryption is in use, then we set bit 3 even
            // if the out is seekable. This is so the check on the last byte of the
            // PKZip Encryption Header can be done on the current time, as opposed to
            // the CRC, to prevent streaming the file twice.  So, test for
            // ZipOutputStream and seekable, and if so, seek back, even if bit 3 is set.

            if ((_BitField & 0x0008) != 0x0008 ||
                 (this._Source == ZipEntrySource.ZipOutputStream && s.CanSeek))
            {
                // seek back and rewrite the entry header
                var zss = s as ZipSegmentedStream;
                if (zss != null && _diskNumber != zss.CurrentSegment)
                {
                    // In this case the entry header is in a different file,
                    // which has already been closed. Need to re-open it.
                    using (Stream hseg = ZipSegmentedStream.ForUpdate(this._container.ZipFile.Name, _diskNumber))
                    {
                        hseg.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin);
                        hseg.Write(_EntryHeader, 0, _EntryHeader.Length);
                    }
                }
                else
                {
                    // seek in the raw output stream, to the beginning of the header for
                    // this entry.
                    // workitem 8098: ok (output)
                    s.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin);

                    // write the updated header to the output stream
                    s.Write(_EntryHeader, 0, _EntryHeader.Length);

                    // adjust the count on the CountingStream as necessary
                    if (s1 != null) s1.Adjust(_EntryHeader.Length);

                    // seek in the raw output stream, to the end of the file data
                    // for this entry
                    s.Seek(_CompressedSize, SeekOrigin.Current);
                }
            }

            // emit the descriptor - only if not a directory.
            if (((_BitField & 0x0008) == 0x0008) && !IsDirectory)
            {
                byte[] Descriptor = new byte[16 + (_OutputUsesZip64.Value ? 8 : 0)];
                i = 0;

                // signature
                Array.Copy(BitConverter.GetBytes(ZipConstants.ZipEntryDataDescriptorSignature), 0, Descriptor, i, 4);
                i += 4;

                // CRC - the correct value now
                Array.Copy(BitConverter.GetBytes(_Crc32), 0, Descriptor, i, 4);
                i += 4;

                // workitem 7917
                if (_OutputUsesZip64.Value)
                {
                    // CompressedSize - the correct value now
                    Array.Copy(BitConverter.GetBytes(_CompressedSize), 0, Descriptor, i, 8);
                    i += 8;

                    // UncompressedSize - the correct value now
                    Array.Copy(BitConverter.GetBytes(_UncompressedSize), 0, Descriptor, i, 8);
                    i += 8;
                }
                else
                {
                    // CompressedSize - (lower 32 bits) the correct value now
                    Descriptor[i++] = (byte)(_CompressedSize & 0x000000FF);
                    Descriptor[i++] = (byte)((_CompressedSize & 0x0000FF00) >> 8);
                    Descriptor[i++] = (byte)((_CompressedSize & 0x00FF0000) >> 16);
                    Descriptor[i++] = (byte)((_CompressedSize & 0xFF000000) >> 24);

                    // UncompressedSize - (lower 32 bits) the correct value now
                    Descriptor[i++] = (byte)(_UncompressedSize & 0x000000FF);
                    Descriptor[i++] = (byte)((_UncompressedSize & 0x0000FF00) >> 8);
                    Descriptor[i++] = (byte)((_UncompressedSize & 0x00FF0000) >> 16);
                    Descriptor[i++] = (byte)((_UncompressedSize & 0xFF000000) >> 24);
                }

                // finally, write the trailing descriptor to the output stream
                s.Write(Descriptor, 0, Descriptor.Length);

                _LengthOfTrailer += Descriptor.Length;
            }
        }
ZipEntry