Beispiel #1
0
        private void _WriteFileData(ZipCrypto cipher, System.IO.Stream s)
        {
            // Read in the data from the input stream (often a file in the filesystem),
            // and write it to the output stream, calculating a CRC on it as we go.
            // We will also deflate and encrypt as necessary.

            Stream input = null;
            CrcCalculatorStream input1 = null;
            CountingStream counter = null;
            try {
            // s.Position may fail on some write-only streams, eg stdout or System.Web.HttpResponseStream
            // We swallow that exception, because we don't care!
            this.__FileDataPosition = s.Position;
            } catch{}

            try
            {
                // get the original stream:
                if (_sourceStream != null)
                {
                    _sourceStream.Position = 0;
                    input = _sourceStream;
                }
                else
                {
                    input = System.IO.File.OpenRead(LocalFileName);
                }

                // wrap a CRC Calculator Stream around the raw input stream.
                input1 = new CrcCalculatorStream(input);

                // wrap a counting stream around the raw output stream:
                counter = new CountingStream(s);

                // maybe wrap an encrypting stream around that:
                Stream output1 = (Encryption == EncryptionAlgorithm.PkzipWeak) ?
                    (Stream)(new ZipCipherStream(counter, cipher, CryptoMode.Encrypt)) : counter;

                // maybe wrap a DeflateStream around that
                Stream output2 = null;
                bool mustCloseDeflateStream = false;
                if (CompressionMethod == 0x08)
                {
                    output2 = new DeflateStream(output1, CompressionMode.Compress, true);
                    mustCloseDeflateStream = true;
                }
                else
                    output2 = output1;

                // as we emit the file, we maybe deflate, then maybe encrypt, then write the bytes.
                byte[] buffer = new byte[READBLOCK_SIZE];

                int n = input1.Read(buffer, 0, READBLOCK_SIZE);
                while (n > 0)
                {
                    output2.Write(buffer, 0, n);
                    n = input1.Read(buffer, 0, READBLOCK_SIZE);
                }

                // by calling Close() on the deflate stream, we write the footer bytes, as necessary.
                if (mustCloseDeflateStream)
                    output2.Close();

            }
            finally
            {
                if (_sourceStream == null && input != null)
                {
                    input.Close();
                    input.Dispose();
                }

            }

            _UncompressedSize = input1.TotalBytesSlurped;
            _CompressedSize = counter.BytesWritten;

            _Crc32 = input1.Crc32;

            if ((_Password != null) && (Encryption == EncryptionAlgorithm.PkzipWeak))
            {
                _CompressedSize += 12; // 12 extra bytes for the encryption header
            }

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

            // CompressedSize - the correct value now
            _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);

            // workitem 6414
            if (s.CanSeek)
            {
                // seek in the raw output stream, to the beginning of the header for this entry.
                s.Seek(this._RelativeOffsetOfHeader, System.IO.SeekOrigin.Begin);

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

                // adjust the count on the CountingStream as necessary
                var s1 = s as CountingStream;
                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, System.IO.SeekOrigin.Current);
            }
            else
            {
                // eg, ASP.NET Response.OutputStream, or stdout

                if ((_BitField & 0x0008) != 0x0008)
                    throw new ZipException("Logic error.");

                byte[] Descriptor = new byte[16];
                i = 0;
                // signature
                int sig = ZipConstants.ZipEntryDataDescriptorSignature;
                Descriptor[i++] = (byte)(sig & 0x000000FF);
                Descriptor[i++] = (byte)((sig & 0x0000FF00) >> 8);
                Descriptor[i++] = (byte)((sig & 0x00FF0000) >> 16);
                Descriptor[i++] = (byte)((sig & 0xFF000000) >> 24);

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

                // CompressedSize - 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 - 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 updated header to the output stream
                s.Write(Descriptor, 0, Descriptor.Length);
            }
        }
Beispiel #2
0
        private Int32 _ExtractOne(System.IO.Stream output, ZipCrypto cipher)
        {
            System.IO.Stream input = this.ArchiveStream;

            // seek to the beginning of the file data in the stream
            input.Seek(this.__FileDataPosition, System.IO.SeekOrigin.Begin);

            // to validate the CRC.
            Int32 CrcResult = 0;

            byte[] bytes = new byte[READBLOCK_SIZE];

            // The extraction process varies depending on how the entry was stored.
            // It could have been encrypted, and it coould have been compressed, or both, or
            // neither. So we need to check both the encryption flag and the compression flag,
            // and take the proper action in all cases.

            int LeftToRead = (CompressionMethod == 0x08) ? this.UncompressedSize : this._CompressedFileDataSize;

            // get a stream that either decrypts or not.
            Stream input2 = (Encryption == EncryptionAlgorithm.PkzipWeak)
                ? new ZipCipherStream(input, cipher, CryptoMode.Decrypt)
                : input;

            // using the above, now we get a stream that either decompresses or not.
            Stream input3 = (CompressionMethod == 0x08)
                ? new DeflateStream(input2, CompressionMode.Decompress, true)
                : input2;

            //var out2 = new CrcCalculatorStream(output, LeftToRead);

            // as we read, we maybe decrypt, and then we maybe decompress. Then we write.
            using (var s1 = new CrcCalculatorStream(input3))
            {
                while (LeftToRead > 0)
                {
                    int len = (LeftToRead > bytes.Length) ? bytes.Length : LeftToRead;
                    int n = s1.Read(bytes, 0, len);
                    _CheckRead(n);
                    output.Write(bytes, 0, n);
                    LeftToRead -= n;
                }

                CrcResult = s1.Crc32;
            }

            return CrcResult;
        }