First commit
Send all results
This commit is contained in:
		@@ -0,0 +1,676 @@
 | 
			
		||||
// DeflaterOutputStream.cs
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2001 Mike Krueger
 | 
			
		||||
//
 | 
			
		||||
// This file was translated from java, it was part of the GNU Classpath
 | 
			
		||||
// Copyright (C) 2001 Free Software Foundation, Inc.
 | 
			
		||||
//
 | 
			
		||||
// This program is free software; you can redistribute it and/or
 | 
			
		||||
// modify it under the terms of the GNU General Public License
 | 
			
		||||
// as published by the Free Software Foundation; either version 2
 | 
			
		||||
// of the License, or (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program; if not, write to the Free Software
 | 
			
		||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
			
		||||
//
 | 
			
		||||
// Linking this library statically or dynamically with other modules is
 | 
			
		||||
// making a combined work based on this library.  Thus, the terms and
 | 
			
		||||
// conditions of the GNU General Public License cover the whole
 | 
			
		||||
// combination.
 | 
			
		||||
// 
 | 
			
		||||
// As a special exception, the copyright holders of this library give you
 | 
			
		||||
// permission to link this library with independent modules to produce an
 | 
			
		||||
// executable, regardless of the license terms of these independent
 | 
			
		||||
// modules, and to copy and distribute the resulting executable under
 | 
			
		||||
// terms of your choice, provided that you also meet, for each linked
 | 
			
		||||
// independent module, the terms and conditions of the license of that
 | 
			
		||||
// module.  An independent module is a module which is not derived from
 | 
			
		||||
// or based on this library.  If you modify this library, you may extend
 | 
			
		||||
// this exception to your version of the library, but you are not
 | 
			
		||||
// obligated to do so.  If you do not wish to do so, delete this
 | 
			
		||||
// exception statement from your version.
 | 
			
		||||
 | 
			
		||||
// HISTORY
 | 
			
		||||
//	22-12-2009	DavidPierson	Added AES support
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using PdfSharp.SharpZipLib.Checksums;
 | 
			
		||||
 | 
			
		||||
// ReSharper disable RedundantThisQualifier
 | 
			
		||||
 | 
			
		||||
//#if !NETCF_1_0
 | 
			
		||||
//using System.Security.Cryptography;
 | 
			
		||||
//using PdfSharp.SharpZipLib.Encryption;
 | 
			
		||||
//#endif
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.SharpZipLib.Zip.Compression.Streams
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// A special stream deflating or compressing the bytes that are
 | 
			
		||||
    /// written to it.  It uses a Deflater to perform actual deflating.<br/>
 | 
			
		||||
    /// Authors of the original java version: Tom Tromey, Jochen Hoenicke 
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal class DeflaterOutputStream : Stream
 | 
			
		||||
    {
 | 
			
		||||
        #region Constructors
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new DeflaterOutputStream with a default Deflater and default buffer size.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="baseOutputStream">
 | 
			
		||||
        /// the output stream where deflated output should be written.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        public DeflaterOutputStream(Stream baseOutputStream)
 | 
			
		||||
            : this(baseOutputStream, new Deflater(), 512)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new DeflaterOutputStream with the given Deflater and
 | 
			
		||||
        /// default buffer size.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="baseOutputStream">
 | 
			
		||||
        /// the output stream where deflated output should be written.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="deflater">
 | 
			
		||||
        /// the underlying deflater.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater)
 | 
			
		||||
            : this(baseOutputStream, deflater, 512)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Creates a new DeflaterOutputStream with the given Deflater and
 | 
			
		||||
        /// buffer size.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="baseOutputStream">
 | 
			
		||||
        /// The output stream where deflated output is written.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="deflater">
 | 
			
		||||
        /// The underlying deflater to use
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="bufferSize">
 | 
			
		||||
        /// The buffer size in bytes to use when deflating (minimum value 512)
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <exception cref="ArgumentOutOfRangeException">
 | 
			
		||||
        /// bufsize is less than or equal to zero.
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        /// <exception cref="ArgumentException">
 | 
			
		||||
        /// baseOutputStream does not support writing
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        /// <exception cref="ArgumentNullException">
 | 
			
		||||
        /// deflater instance is null
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int bufferSize)
 | 
			
		||||
        {
 | 
			
		||||
            if (baseOutputStream == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException("baseOutputStream");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (baseOutputStream.CanWrite == false)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException("Must support writing", "baseOutputStream");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (deflater == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException("deflater");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (bufferSize < 512)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentOutOfRangeException("bufferSize");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            baseOutputStream_ = baseOutputStream;
 | 
			
		||||
            buffer_ = new byte[bufferSize];
 | 
			
		||||
            deflater_ = deflater;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Public API
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Finishes the stream by calling finish() on the deflater. 
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <exception cref="SharpZipBaseException">
 | 
			
		||||
        /// Not all input is deflated
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public virtual void Finish()
 | 
			
		||||
        {
 | 
			
		||||
            deflater_.Finish();
 | 
			
		||||
            while (!deflater_.IsFinished)
 | 
			
		||||
            {
 | 
			
		||||
                int len = deflater_.Deflate(buffer_, 0, buffer_.Length);
 | 
			
		||||
                if (len <= 0)
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
                if (keys != null)
 | 
			
		||||
                {
 | 
			
		||||
#else
 | 
			
		||||
				if (cryptoTransform_ != null) {
 | 
			
		||||
#endif
 | 
			
		||||
                    EncryptBlock(buffer_, 0, len);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                baseOutputStream_.Write(buffer_, 0, len);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!deflater_.IsFinished)
 | 
			
		||||
            {
 | 
			
		||||
                throw new SharpZipBaseException("Can't deflate all input?");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            baseOutputStream_.Flush();
 | 
			
		||||
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
            if (keys != null)
 | 
			
		||||
            {
 | 
			
		||||
                keys = null;
 | 
			
		||||
            }
 | 
			
		||||
#else
 | 
			
		||||
			if (cryptoTransform_ != null) {
 | 
			
		||||
#if !NET_1_1 && !NETCF_2_0
 | 
			
		||||
				if (cryptoTransform_ is ZipAESTransform) {
 | 
			
		||||
					AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode();
 | 
			
		||||
				}
 | 
			
		||||
#endif
 | 
			
		||||
				cryptoTransform_.Dispose();
 | 
			
		||||
				cryptoTransform_ = null;
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get/set flag indicating ownership of the underlying stream.
 | 
			
		||||
        /// When the flag is true <see cref="Close"></see> will close the underlying stream also.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IsStreamOwner
 | 
			
		||||
        {
 | 
			
		||||
            get { return isStreamOwner_; }
 | 
			
		||||
            set { isStreamOwner_ = value; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ///	<summary>
 | 
			
		||||
        /// Allows client to determine if an entry can be patched after its added
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool CanPatchEntries
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return baseOutputStream_.CanSeek;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Encryption
 | 
			
		||||
 | 
			
		||||
        string password;
 | 
			
		||||
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
        uint[] keys;
 | 
			
		||||
#else
 | 
			
		||||
		ICryptoTransform cryptoTransform_;
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Returns the 10 byte AUTH CODE to be appended immediately following the AES data stream.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		protected byte[] AESAuthCode;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get/set the password used for encryption.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>When set to null or if the password is empty no encryption is performed</remarks>
 | 
			
		||||
        public string Password
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return password;
 | 
			
		||||
            }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                if ((value != null) && (value.Length == 0))
 | 
			
		||||
                {
 | 
			
		||||
                    password = null;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    password = value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypt a block of data
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">
 | 
			
		||||
        /// Data to encrypt.  NOTE the original contents of the buffer are lost
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="offset">
 | 
			
		||||
        /// Offset of first byte in buffer to encrypt
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="length">
 | 
			
		||||
        /// Number of bytes in buffer to encrypt
 | 
			
		||||
        /// </param>
 | 
			
		||||
        protected void EncryptBlock(byte[] buffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
            for (int i = offset; i < offset + length; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                byte oldbyte = buffer[i];
 | 
			
		||||
                buffer[i] ^= EncryptByte();
 | 
			
		||||
                UpdateKeys(oldbyte);
 | 
			
		||||
            }
 | 
			
		||||
#else
 | 
			
		||||
			cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes encryption keys based on given <paramref name="password"/>.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="password">The password.</param>
 | 
			
		||||
        protected void InitializePassword(string password)
 | 
			
		||||
        {
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
            keys = new uint[] {
 | 
			
		||||
				0x12345678,
 | 
			
		||||
				0x23456789,
 | 
			
		||||
				0x34567890
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
            byte[] rawPassword = ZipConstants.ConvertToArray(password);
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < rawPassword.Length; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                UpdateKeys((byte)rawPassword[i]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
#else			
 | 
			
		||||
			PkzipClassicManaged pkManaged = new PkzipClassicManaged();
 | 
			
		||||
			byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password));
 | 
			
		||||
			cryptoTransform_ = pkManaged.CreateEncryptor(key, null);
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if false//!NET_1_1 && !NETCF_2_0
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Initializes encryption keys based on given password.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		protected void InitializeAESPassword(ZipEntry entry, string rawPassword,
 | 
			
		||||
											out byte[] salt, out byte[] pwdVerifier) {
 | 
			
		||||
			salt = new byte[entry.AESSaltLen];
 | 
			
		||||
			// Salt needs to be cryptographically random, and unique per file
 | 
			
		||||
			if (_aesRnd == null)
 | 
			
		||||
				_aesRnd = new RNGCryptoServiceProvider();
 | 
			
		||||
			_aesRnd.GetBytes(salt);
 | 
			
		||||
			int blockSize = entry.AESKeySize / 8;	// bits to bytes
 | 
			
		||||
 | 
			
		||||
			cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true);
 | 
			
		||||
			pwdVerifier = ((ZipAESTransform)cryptoTransform_).PwdVerifier;
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Encrypt a single byte 
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// The encrypted value
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        protected byte EncryptByte()
 | 
			
		||||
        {
 | 
			
		||||
            uint temp = ((keys[2] & 0xFFFF) | 2);
 | 
			
		||||
            return (byte)((temp * (temp ^ 1)) >> 8);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Update encryption keys 
 | 
			
		||||
        /// </summary>		
 | 
			
		||||
        protected void UpdateKeys(byte ch)
 | 
			
		||||
        {
 | 
			
		||||
            keys[0] = Crc32.ComputeCrc32(keys[0], ch);
 | 
			
		||||
            keys[1] = keys[1] + (byte)keys[0];
 | 
			
		||||
            keys[1] = keys[1] * 134775813 + 1;
 | 
			
		||||
            keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24));
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Deflation Support
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Deflates everything in the input buffers.  This will call
 | 
			
		||||
        /// <code>def.deflate()</code> until all bytes from the input buffers
 | 
			
		||||
        /// are processed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected void Deflate()
 | 
			
		||||
        {
 | 
			
		||||
            while (!deflater_.IsNeedingInput)
 | 
			
		||||
            {
 | 
			
		||||
                int deflateCount = deflater_.Deflate(buffer_, 0, buffer_.Length);
 | 
			
		||||
 | 
			
		||||
                if (deflateCount <= 0)
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
                if (keys != null)
 | 
			
		||||
#else
 | 
			
		||||
				if (cryptoTransform_ != null) 
 | 
			
		||||
#endif
 | 
			
		||||
                {
 | 
			
		||||
                    EncryptBlock(buffer_, 0, deflateCount);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                baseOutputStream_.Write(buffer_, 0, deflateCount);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!deflater_.IsNeedingInput)
 | 
			
		||||
            {
 | 
			
		||||
                throw new SharpZipBaseException("DeflaterOutputStream can't deflate all input?");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Stream Overrides
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets value indicating stream can be read from
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override bool CanRead
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets a value indicating if seeking is supported for this stream
 | 
			
		||||
        /// This property always returns false
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override bool CanSeek
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get value indicating if this stream supports writing
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override bool CanWrite
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return baseOutputStream_.CanWrite;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get current length of stream
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override long Length
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return baseOutputStream_.Length;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets the current position within the stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any attempt to set position</exception>
 | 
			
		||||
        public override long Position
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return baseOutputStream_.Position;
 | 
			
		||||
            }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                throw new NotSupportedException("Position property not supported");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the current position of this stream to the given value. Not supported by this class!
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="offset">The offset relative to the <paramref name="origin"/> to seek.</param>
 | 
			
		||||
        /// <param name="origin">The <see cref="SeekOrigin"/> to seek from.</param>
 | 
			
		||||
        /// <returns>The new position in the stream.</returns>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override long Seek(long offset, SeekOrigin origin)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("DeflaterOutputStream Seek not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the length of this stream to the given value. Not supported by this class!
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="value">The new stream length.</param>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override void SetLength(long value)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("DeflaterOutputStream SetLength not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read a byte from stream advancing position by one
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The byte read cast to an int.  THe value is -1 if at the end of the stream.</returns>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override int ReadByte()
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("DeflaterOutputStream ReadByte not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read a block of bytes from stream
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">The buffer to store read data in.</param>
 | 
			
		||||
        /// <param name="offset">The offset to start storing at.</param>
 | 
			
		||||
        /// <param name="count">The maximum number of bytes to read.</param>
 | 
			
		||||
        /// <returns>The actual number of bytes read.  Zero if end of stream is detected.</returns>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override int Read(byte[] buffer, int offset, int count)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("DeflaterOutputStream Read not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if !NETFX_CORE && !UWP
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Asynchronous reads are not supported a NotSupportedException is always thrown
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="buffer">The buffer to read into.</param>
 | 
			
		||||
		/// <param name="offset">The offset to start storing data at.</param>
 | 
			
		||||
		/// <param name="count">The number of bytes to read</param>
 | 
			
		||||
		/// <param name="callback">The async callback to use.</param>
 | 
			
		||||
		/// <param name="state">The state to use.</param>
 | 
			
		||||
		/// <returns>Returns an <see cref="IAsyncResult"/></returns>
 | 
			
		||||
		/// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
		public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("DeflaterOutputStream BeginRead not currently supported");
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !NETFX_CORE && !UWP
 | 
			
		||||
        /// <summary>
 | 
			
		||||
		/// Asynchronous writes arent supported, a NotSupportedException is always thrown
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="buffer">The buffer to write.</param>
 | 
			
		||||
		/// <param name="offset">The offset to begin writing at.</param>
 | 
			
		||||
		/// <param name="count">The number of bytes to write.</param>
 | 
			
		||||
		/// <param name="callback">The <see cref="AsyncCallback"/> to use.</param>
 | 
			
		||||
		/// <param name="state">The state object.</param>
 | 
			
		||||
		/// <returns>Returns an IAsyncResult.</returns>
 | 
			
		||||
		/// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
		public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotSupportedException("BeginWrite is not supported");
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Flushes the stream by calling <see cref="DeflaterOutputStream.Flush">Flush</see> on the deflater and then
 | 
			
		||||
        /// on the underlying stream.  This ensures that all bytes are flushed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override void Flush()
 | 
			
		||||
        {
 | 
			
		||||
            deflater_.Flush();
 | 
			
		||||
            Deflate();
 | 
			
		||||
            baseOutputStream_.Flush();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if !NETFX_CORE && !UWP
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Calls <see cref="Finish"/> and closes the underlying
 | 
			
		||||
		/// stream when <see cref="IsStreamOwner"></see> is true.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public override void Close()
 | 
			
		||||
		{
 | 
			
		||||
			if ( !isClosed_ ) {
 | 
			
		||||
				isClosed_ = true;
 | 
			
		||||
 | 
			
		||||
				try {
 | 
			
		||||
					Finish();
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
                    keys =null;
 | 
			
		||||
#else
 | 
			
		||||
					if ( cryptoTransform_ != null ) {
 | 
			
		||||
						GetAuthCodeIfAES();
 | 
			
		||||
						cryptoTransform_.Dispose();
 | 
			
		||||
						cryptoTransform_ = null;
 | 
			
		||||
					}
 | 
			
		||||
#endif
 | 
			
		||||
				}
 | 
			
		||||
				finally {
 | 
			
		||||
					if( isStreamOwner_ ) {
 | 
			
		||||
						baseOutputStream_.Close();
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#else
 | 
			
		||||
        public void Close()
 | 
			
		||||
        {
 | 
			
		||||
            if (!isClosed_)
 | 
			
		||||
            {
 | 
			
		||||
                isClosed_ = true;
 | 
			
		||||
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    Finish();
 | 
			
		||||
#if true//NETCF_1_0
 | 
			
		||||
                    keys = null;
 | 
			
		||||
#else
 | 
			
		||||
					if ( cryptoTransform_ != null ) {
 | 
			
		||||
						GetAuthCodeIfAES();
 | 
			
		||||
						cryptoTransform_.Dispose();
 | 
			
		||||
						cryptoTransform_ = null;
 | 
			
		||||
					}
 | 
			
		||||
#endif
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    if (isStreamOwner_)
 | 
			
		||||
                    {
 | 
			
		||||
                        //baseOutputStream_.Close();
 | 
			
		||||
                        baseOutputStream_.Dispose();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private void GetAuthCodeIfAES()
 | 
			
		||||
        {
 | 
			
		||||
#if false//!NET_1_1 && !NETCF_2_0
 | 
			
		||||
			if (cryptoTransform_ is ZipAESTransform) {
 | 
			
		||||
				AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode();
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Writes a single byte to the compressed output stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="value">
 | 
			
		||||
        /// The byte value.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        public override void WriteByte(byte value)
 | 
			
		||||
        {
 | 
			
		||||
            byte[] b = new byte[1];
 | 
			
		||||
            b[0] = value;
 | 
			
		||||
            Write(b, 0, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Writes bytes from an array to the compressed stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">
 | 
			
		||||
        /// The byte array
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="offset">
 | 
			
		||||
        /// The offset into the byte array where to start.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="count">
 | 
			
		||||
        /// The number of bytes to write.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        public override void Write(byte[] buffer, int offset, int count)
 | 
			
		||||
        {
 | 
			
		||||
            deflater_.SetInput(buffer, offset, count);
 | 
			
		||||
            Deflate();
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Instance Fields
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// This buffer is used temporarily to retrieve the bytes from the
 | 
			
		||||
        /// deflater and write them to the underlying output stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        byte[] buffer_;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The deflater which is used to deflate the stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected Deflater deflater_;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Base stream the deflater depends on.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected Stream baseOutputStream_;
 | 
			
		||||
 | 
			
		||||
#if true || !NETFX_CORE && !UWP
 | 
			
		||||
        bool isClosed_;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        bool isStreamOwner_ = true;
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Static Fields
 | 
			
		||||
 | 
			
		||||
#if false//!NET_1_1 && !NETCF_2_0
 | 
			
		||||
		// Static to help ensure that multiple files within a zip will get different random salt
 | 
			
		||||
		private static RNGCryptoServiceProvider _aesRnd;
 | 
			
		||||
#endif
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,811 @@
 | 
			
		||||
// InflaterInputStream.cs
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2001 Mike Krueger
 | 
			
		||||
// Copyright (C) 2004 John Reilly
 | 
			
		||||
//
 | 
			
		||||
// This file was translated from java, it was part of the GNU Classpath
 | 
			
		||||
// Copyright (C) 2001 Free Software Foundation, Inc.
 | 
			
		||||
//
 | 
			
		||||
// This program is free software; you can redistribute it and/or
 | 
			
		||||
// modify it under the terms of the GNU General Public License
 | 
			
		||||
// as published by the Free Software Foundation; either version 2
 | 
			
		||||
// of the License, or (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program; if not, write to the Free Software
 | 
			
		||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
			
		||||
//
 | 
			
		||||
// Linking this library statically or dynamically with other modules is
 | 
			
		||||
// making a combined work based on this library.  Thus, the terms and
 | 
			
		||||
// conditions of the GNU General Public License cover the whole
 | 
			
		||||
// combination.
 | 
			
		||||
// 
 | 
			
		||||
// As a special exception, the copyright holders of this library give you
 | 
			
		||||
// permission to link this library with independent modules to produce an
 | 
			
		||||
// executable, regardless of the license terms of these independent
 | 
			
		||||
// modules, and to copy and distribute the resulting executable under
 | 
			
		||||
// terms of your choice, provided that you also meet, for each linked
 | 
			
		||||
// independent module, the terms and conditions of the license of that
 | 
			
		||||
// module.  An independent module is a module which is not derived from
 | 
			
		||||
// or based on this library.  If you modify this library, you may extend
 | 
			
		||||
// this exception to your version of the library, but you are not
 | 
			
		||||
// obligated to do so.  If you do not wish to do so, delete this
 | 
			
		||||
// exception statement from your version.
 | 
			
		||||
 | 
			
		||||
// HISTORY
 | 
			
		||||
//	11-08-2009	GeoffHart	T9121	Added Multi-member gzip support
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
 | 
			
		||||
// ReSharper disable RedundantThisQualifier
 | 
			
		||||
 | 
			
		||||
#if false//!NETCF_1_0
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.SharpZipLib.Zip.Compression.Streams
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// An input buffer customised for use by <see cref="InflaterInputStream"/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <remarks>
 | 
			
		||||
    /// The buffer supports decryption of incoming data.
 | 
			
		||||
    /// </remarks>
 | 
			
		||||
    internal class InflaterInputBuffer
 | 
			
		||||
    {
 | 
			
		||||
        #region Constructors
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initialise a new instance of <see cref="InflaterInputBuffer"/> with a default buffer size
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="stream">The stream to buffer.</param>
 | 
			
		||||
        public InflaterInputBuffer(Stream stream)
 | 
			
		||||
            : this(stream, 4096)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initialise a new instance of <see cref="InflaterInputBuffer"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="stream">The stream to buffer.</param>
 | 
			
		||||
        /// <param name="bufferSize">The size to use for the buffer</param>
 | 
			
		||||
        /// <remarks>A minimum buffer size of 1KB is permitted.  Lower sizes are treated as 1KB.</remarks>
 | 
			
		||||
        public InflaterInputBuffer(Stream stream, int bufferSize)
 | 
			
		||||
        {
 | 
			
		||||
            inputStream = stream;
 | 
			
		||||
            if (bufferSize < 1024)
 | 
			
		||||
            {
 | 
			
		||||
                bufferSize = 1024;
 | 
			
		||||
            }
 | 
			
		||||
            rawData = new byte[bufferSize];
 | 
			
		||||
            clearText = rawData;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get the length of bytes bytes in the <see cref="RawData"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int RawLength
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return rawLength;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get the contents of the raw data buffer.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>This may contain encrypted data.</remarks>
 | 
			
		||||
        public byte[] RawData
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return rawData;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get the number of useable bytes in <see cref="ClearText"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int ClearTextLength
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return clearTextLength;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get the contents of the clear text buffer.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public byte[] ClearText
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return clearText;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get/set the number of bytes available
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int Available
 | 
			
		||||
        {
 | 
			
		||||
            get { return available; }
 | 
			
		||||
            set { available = value; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Call <see cref="Inflater.SetInput(byte[], int, int)"/> passing the current clear text buffer contents.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="inflater">The inflater to set input for.</param>
 | 
			
		||||
        public void SetInflaterInput(Inflater inflater)
 | 
			
		||||
        {
 | 
			
		||||
            if (available > 0)
 | 
			
		||||
            {
 | 
			
		||||
                inflater.SetInput(clearText, clearTextLength - available, available);
 | 
			
		||||
                available = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Fill the buffer from the underlying input stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Fill()
 | 
			
		||||
        {
 | 
			
		||||
            rawLength = 0;
 | 
			
		||||
            int toRead = rawData.Length;
 | 
			
		||||
 | 
			
		||||
            while (toRead > 0)
 | 
			
		||||
            {
 | 
			
		||||
                int count = inputStream.Read(rawData, rawLength, toRead);
 | 
			
		||||
                if (count <= 0)
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                rawLength += count;
 | 
			
		||||
                toRead -= count;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
#if false//!NETCF_1_0
 | 
			
		||||
			if ( cryptoTransform != null ) {
 | 
			
		||||
				clearTextLength = cryptoTransform.TransformBlock(rawData, 0, rawLength, clearText, 0);
 | 
			
		||||
			}
 | 
			
		||||
			else 
 | 
			
		||||
#endif
 | 
			
		||||
            {
 | 
			
		||||
                clearTextLength = rawLength;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            available = clearTextLength;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read a buffer directly from the input stream
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">The buffer to fill</param>
 | 
			
		||||
        /// <returns>Returns the number of bytes read.</returns>
 | 
			
		||||
        public int ReadRawBuffer(byte[] buffer)
 | 
			
		||||
        {
 | 
			
		||||
            return ReadRawBuffer(buffer, 0, buffer.Length);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read a buffer directly from the input stream
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="outBuffer">The buffer to read into</param>
 | 
			
		||||
        /// <param name="offset">The offset to start reading data into.</param>
 | 
			
		||||
        /// <param name="length">The number of bytes to read.</param>
 | 
			
		||||
        /// <returns>Returns the number of bytes read.</returns>
 | 
			
		||||
        public int ReadRawBuffer(byte[] outBuffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            if (length < 0)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentOutOfRangeException("length");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int currentOffset = offset;
 | 
			
		||||
            int currentLength = length;
 | 
			
		||||
 | 
			
		||||
            while (currentLength > 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (available <= 0)
 | 
			
		||||
                {
 | 
			
		||||
                    Fill();
 | 
			
		||||
                    if (available <= 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        return 0;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                int toCopy = Math.Min(currentLength, available);
 | 
			
		||||
                System.Array.Copy(rawData, rawLength - (int)available, outBuffer, currentOffset, toCopy);
 | 
			
		||||
                currentOffset += toCopy;
 | 
			
		||||
                currentLength -= toCopy;
 | 
			
		||||
                available -= toCopy;
 | 
			
		||||
            }
 | 
			
		||||
            return length;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read clear text data from the input stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="outBuffer">The buffer to add data to.</param>
 | 
			
		||||
        /// <param name="offset">The offset to start adding data at.</param>
 | 
			
		||||
        /// <param name="length">The number of bytes to read.</param>
 | 
			
		||||
        /// <returns>Returns the number of bytes actually read.</returns>
 | 
			
		||||
        public int ReadClearTextBuffer(byte[] outBuffer, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            if (length < 0)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentOutOfRangeException("length");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int currentOffset = offset;
 | 
			
		||||
            int currentLength = length;
 | 
			
		||||
 | 
			
		||||
            while (currentLength > 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (available <= 0)
 | 
			
		||||
                {
 | 
			
		||||
                    Fill();
 | 
			
		||||
                    if (available <= 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        return 0;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                int toCopy = Math.Min(currentLength, available);
 | 
			
		||||
                Array.Copy(clearText, clearTextLength - (int)available, outBuffer, currentOffset, toCopy);
 | 
			
		||||
                currentOffset += toCopy;
 | 
			
		||||
                currentLength -= toCopy;
 | 
			
		||||
                available -= toCopy;
 | 
			
		||||
            }
 | 
			
		||||
            return length;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read a <see cref="byte"/> from the input stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>Returns the byte read.</returns>
 | 
			
		||||
        public int ReadLeByte()
 | 
			
		||||
        {
 | 
			
		||||
            if (available <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                Fill();
 | 
			
		||||
                if (available <= 0)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new ZipException("EOF in header");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            byte result = rawData[rawLength - available];
 | 
			
		||||
            available -= 1;
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read an <see cref="short"/> in little endian byte order.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The short value read case to an int.</returns>
 | 
			
		||||
        public int ReadLeShort()
 | 
			
		||||
        {
 | 
			
		||||
            return ReadLeByte() | (ReadLeByte() << 8);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read an <see cref="int"/> in little endian byte order.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The int value read.</returns>
 | 
			
		||||
        public int ReadLeInt()
 | 
			
		||||
        {
 | 
			
		||||
            return ReadLeShort() | (ReadLeShort() << 16);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read a <see cref="long"/> in little endian byte order.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>The long value read.</returns>
 | 
			
		||||
        public long ReadLeLong()
 | 
			
		||||
        {
 | 
			
		||||
            return (uint)ReadLeInt() | ((long)ReadLeInt() << 32);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if false//!NETCF_1_0
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Get/set the <see cref="ICryptoTransform"/> to apply to any data.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <remarks>Set this value to null to have no transform applied.</remarks>
 | 
			
		||||
		public ICryptoTransform CryptoTransform
 | 
			
		||||
		{
 | 
			
		||||
			set { 
 | 
			
		||||
				cryptoTransform = value;
 | 
			
		||||
				if ( cryptoTransform != null ) {
 | 
			
		||||
					if ( rawData == clearText ) {
 | 
			
		||||
						if ( internalClearText == null ) {
 | 
			
		||||
							internalClearText = new byte[rawData.Length];
 | 
			
		||||
						}
 | 
			
		||||
						clearText = internalClearText;
 | 
			
		||||
					}
 | 
			
		||||
					clearTextLength = rawLength;
 | 
			
		||||
					if ( available > 0 ) {
 | 
			
		||||
						cryptoTransform.TransformBlock(rawData, rawLength - available, available, clearText, rawLength - available);
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					clearText = rawData;
 | 
			
		||||
					clearTextLength = rawLength;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        #region Instance Fields
 | 
			
		||||
        int rawLength;
 | 
			
		||||
        byte[] rawData;
 | 
			
		||||
 | 
			
		||||
        int clearTextLength;
 | 
			
		||||
        byte[] clearText;
 | 
			
		||||
#if false//!NETCF_1_0		
 | 
			
		||||
		byte[] internalClearText;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        int available;
 | 
			
		||||
 | 
			
		||||
#if false//!NETCF_1_0
 | 
			
		||||
		ICryptoTransform cryptoTransform;
 | 
			
		||||
#endif
 | 
			
		||||
        Stream inputStream;
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// This filter stream is used to decompress data compressed using the "deflate"
 | 
			
		||||
    /// format. The "deflate" format is described in RFC 1951.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This stream may form the basis for other decompression filters, such
 | 
			
		||||
    /// as the GZipInputStream.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Author of the original java version: John Leuner.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal class InflaterInputStream : Stream
 | 
			
		||||
    {
 | 
			
		||||
        #region Constructors
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create an InflaterInputStream with the default decompressor
 | 
			
		||||
        /// and a default buffer size of 4KB.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name = "baseInputStream">
 | 
			
		||||
        /// The InputStream to read bytes from
 | 
			
		||||
        /// </param>
 | 
			
		||||
        public InflaterInputStream(Stream baseInputStream)
 | 
			
		||||
            : this(baseInputStream, new Inflater(), 4096)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create an InflaterInputStream with the specified decompressor
 | 
			
		||||
        /// and a default buffer size of 4KB.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name = "baseInputStream">
 | 
			
		||||
        /// The source of input data
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name = "inf">
 | 
			
		||||
        /// The decompressor used to decompress data read from baseInputStream
 | 
			
		||||
        /// </param>
 | 
			
		||||
        public InflaterInputStream(Stream baseInputStream, Inflater inf)
 | 
			
		||||
            : this(baseInputStream, inf, 4096)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create an InflaterInputStream with the specified decompressor
 | 
			
		||||
        /// and the specified buffer size.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name = "baseInputStream">
 | 
			
		||||
        /// The InputStream to read bytes from
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name = "inflater">
 | 
			
		||||
        /// The decompressor to use
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name = "bufferSize">
 | 
			
		||||
        /// Size of the buffer to use
 | 
			
		||||
        /// </param>
 | 
			
		||||
        public InflaterInputStream(Stream baseInputStream, Inflater inflater, int bufferSize)
 | 
			
		||||
        {
 | 
			
		||||
            if (baseInputStream == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException("baseInputStream");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (inflater == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException("inflater");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (bufferSize <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentOutOfRangeException("bufferSize");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.baseInputStream = baseInputStream;
 | 
			
		||||
            this.inf = inflater;
 | 
			
		||||
 | 
			
		||||
            inputBuffer = new InflaterInputBuffer(baseInputStream, bufferSize);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get/set flag indicating ownership of underlying stream.
 | 
			
		||||
        /// When the flag is true <see cref="Close"/> will close the underlying stream also.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// The default value is true.
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public bool IsStreamOwner
 | 
			
		||||
        {
 | 
			
		||||
            get { return isStreamOwner; }
 | 
			
		||||
            set { isStreamOwner = value; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Skip specified number of bytes of uncompressed data
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name ="count">
 | 
			
		||||
        /// Number of bytes to skip
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// The number of bytes skipped, zero if the end of 
 | 
			
		||||
        /// stream has been reached
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        /// <exception cref="ArgumentOutOfRangeException">
 | 
			
		||||
        /// <paramref name="count">The number of bytes</paramref> to skip is less than or equal to zero.
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public long Skip(long count)
 | 
			
		||||
        {
 | 
			
		||||
            if (count <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentOutOfRangeException("count");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // v0.80 Skip by seeking if underlying stream supports it...
 | 
			
		||||
            if (baseInputStream.CanSeek)
 | 
			
		||||
            {
 | 
			
		||||
                baseInputStream.Seek(count, SeekOrigin.Current);
 | 
			
		||||
                return count;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                int length = 2048;
 | 
			
		||||
                if (count < length)
 | 
			
		||||
                {
 | 
			
		||||
                    length = (int)count;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                byte[] tmp = new byte[length];
 | 
			
		||||
                int readCount = 1;
 | 
			
		||||
                long toSkip = count;
 | 
			
		||||
 | 
			
		||||
                while ((toSkip > 0) && (readCount > 0))
 | 
			
		||||
                {
 | 
			
		||||
                    if (toSkip < length)
 | 
			
		||||
                    {
 | 
			
		||||
                        length = (int)toSkip;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    readCount = baseInputStream.Read(tmp, 0, length);
 | 
			
		||||
                    toSkip -= readCount;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return count - toSkip;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Clear any cryptographic state.
 | 
			
		||||
        /// </summary>		
 | 
			
		||||
        protected void StopDecrypting()
 | 
			
		||||
        {
 | 
			
		||||
#if false//!NETCF_1_0			
 | 
			
		||||
			inputBuffer.CryptoTransform = null;
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns 0 once the end of the stream (EOF) has been reached.
 | 
			
		||||
        /// Otherwise returns 1.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public virtual int Available
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return inf.IsFinished ? 0 : 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Fills the buffer with more data to decompress.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <exception cref="SharpZipBaseException">
 | 
			
		||||
        /// Stream ends early
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        protected void Fill()
 | 
			
		||||
        {
 | 
			
		||||
            // Protect against redundant calls
 | 
			
		||||
            if (inputBuffer.Available <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                inputBuffer.Fill();
 | 
			
		||||
                if (inputBuffer.Available <= 0)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new SharpZipBaseException("Unexpected EOF");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            inputBuffer.SetInflaterInput(inf);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Stream Overrides
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets a value indicating whether the current stream supports reading
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override bool CanRead
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return baseInputStream.CanRead;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets a value of false indicating seeking is not supported for this stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override bool CanSeek
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets a value of false indicating that this stream is not writeable.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override bool CanWrite
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// A value representing the length of the stream in bytes.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override long Length
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return inputBuffer.RawLength;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// The current position within the stream.
 | 
			
		||||
        /// Throws a NotSupportedException when attempting to set the position
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Attempting to set the position</exception>
 | 
			
		||||
        public override long Position
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return baseInputStream.Position;
 | 
			
		||||
            }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                throw new NotSupportedException("InflaterInputStream Position not supported");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Flushes the baseInputStream
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override void Flush()
 | 
			
		||||
        {
 | 
			
		||||
            baseInputStream.Flush();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Sets the position within the current stream
 | 
			
		||||
        /// Always throws a NotSupportedException
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="offset">The relative offset to seek to.</param>
 | 
			
		||||
        /// <param name="origin">The <see cref="SeekOrigin"/> defining where to seek from.</param>
 | 
			
		||||
        /// <returns>The new position in the stream.</returns>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override long Seek(long offset, SeekOrigin origin)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("Seek not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Set the length of the current stream
 | 
			
		||||
        /// Always throws a NotSupportedException
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="value">The new length value for the stream.</param>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override void SetLength(long value)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("InflaterInputStream SetLength not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Writes a sequence of bytes to stream and advances the current position
 | 
			
		||||
        /// This method always throws a NotSupportedException
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">Thew buffer containing data to write.</param>
 | 
			
		||||
        /// <param name="offset">The offset of the first byte to write.</param>
 | 
			
		||||
        /// <param name="count">The number of bytes to write.</param>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override void Write(byte[] buffer, int offset, int count)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("InflaterInputStream Write not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Writes one byte to the current stream and advances the current position
 | 
			
		||||
        /// Always throws a NotSupportedException
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="value">The byte to write.</param>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override void WriteByte(byte value)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("InflaterInputStream WriteByte not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
#if !NETFX_CORE && !UWP
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Entry point to begin an asynchronous write.  Always throws a NotSupportedException.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">The buffer to write data from</param>
 | 
			
		||||
        /// <param name="offset">Offset of first byte to write</param>
 | 
			
		||||
        /// <param name="count">The maximum number of bytes to write</param>
 | 
			
		||||
        /// <param name="callback">The method to be called when the asynchronous write operation is completed</param>
 | 
			
		||||
        /// <param name="state">A user-provided object that distinguishes this particular asynchronous write request from other requests</param>
 | 
			
		||||
        /// <returns>An <see cref="System.IAsyncResult">IAsyncResult</see> that references the asynchronous write</returns>
 | 
			
		||||
        /// <exception cref="NotSupportedException">Any access</exception>
 | 
			
		||||
        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotSupportedException("InflaterInputStream BeginWrite not supported");
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !NETFX_CORE && !UWP
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Closes the input stream.  When <see cref="IsStreamOwner"></see>
 | 
			
		||||
        /// is true the underlying stream is also closed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public override void Close()
 | 
			
		||||
        {
 | 
			
		||||
            if (!isClosed)
 | 
			
		||||
            {
 | 
			
		||||
                isClosed = true;
 | 
			
		||||
                if (isStreamOwner)
 | 
			
		||||
                {
 | 
			
		||||
                    baseInputStream.Close();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
        public  void Close()
 | 
			
		||||
        {
 | 
			
		||||
            if (!isClosed)
 | 
			
		||||
            {
 | 
			
		||||
                isClosed = true;
 | 
			
		||||
                if (isStreamOwner)
 | 
			
		||||
                {
 | 
			
		||||
                    //baseInputStream.Close();
 | 
			
		||||
                    baseInputStream.Dispose();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Reads decompressed data into the provided buffer byte array
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name ="buffer">
 | 
			
		||||
        /// The array to read and decompress data into
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name ="offset">
 | 
			
		||||
        /// The offset indicating where the data should be placed
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name ="count">
 | 
			
		||||
        /// The number of bytes to decompress
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <returns>The number of bytes read.  Zero signals the end of stream</returns>
 | 
			
		||||
        /// <exception cref="SharpZipBaseException">
 | 
			
		||||
        /// Inflater needs a dictionary
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public override int Read(byte[] buffer, int offset, int count)
 | 
			
		||||
        {
 | 
			
		||||
            if (inf.IsNeedingDictionary)
 | 
			
		||||
            {
 | 
			
		||||
                throw new SharpZipBaseException("Need a dictionary");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int remainingBytes = count;
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                int bytesRead = inf.Inflate(buffer, offset, remainingBytes);
 | 
			
		||||
                offset += bytesRead;
 | 
			
		||||
                remainingBytes -= bytesRead;
 | 
			
		||||
 | 
			
		||||
                if (remainingBytes == 0 || inf.IsFinished)
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (inf.IsNeedingInput)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        Fill();
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (SharpZipBaseException ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        // Hack 16-05-25: Some PDF files lead to an "Unexpected EOF" exception. Is it safe to ignore this exception?
 | 
			
		||||
                        if (ex.Message != "Unexpected EOF")
 | 
			
		||||
                            throw;
 | 
			
		||||
                        // WB! early EOF: apparently not a big deal for some PDF pages: break out of the loop.
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else if (bytesRead == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    throw new ZipException("Don't know what to do");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return count - remainingBytes;
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Instance Fields
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Decompressor for this stream
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected Inflater inf;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// <see cref="InflaterInputBuffer">Input buffer</see> for this stream.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected InflaterInputBuffer inputBuffer;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Base stream the inflater reads from.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private Stream baseInputStream;
 | 
			
		||||
 | 
			
		||||
        ///// <summary>
 | 
			
		||||
        ///// The compressed size
 | 
			
		||||
        ///// </summary>
 | 
			
		||||
        ////protected long csize;
 | 
			
		||||
 | 
			
		||||
#if true || !NETFX_CORE
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Flag indicating wether this instance has been closed or not.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        bool isClosed;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Flag indicating wether this instance is designated the stream owner.
 | 
			
		||||
        /// When closing if this flag is true the underlying stream is closed.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        bool isStreamOwner = true;
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										256
									
								
								PdfSharp/SharpZipLib/Zip/Compression/Streams/OutputWindow.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								PdfSharp/SharpZipLib/Zip/Compression/Streams/OutputWindow.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,256 @@
 | 
			
		||||
// OutputWindow.cs
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2001 Mike Krueger
 | 
			
		||||
//
 | 
			
		||||
// This file was translated from java, it was part of the GNU Classpath
 | 
			
		||||
// Copyright (C) 2001 Free Software Foundation, Inc.
 | 
			
		||||
//
 | 
			
		||||
// This program is free software; you can redistribute it and/or
 | 
			
		||||
// modify it under the terms of the GNU General Public License
 | 
			
		||||
// as published by the Free Software Foundation; either version 2
 | 
			
		||||
// of the License, or (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program; if not, write to the Free Software
 | 
			
		||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
			
		||||
//
 | 
			
		||||
// Linking this library statically or dynamically with other modules is
 | 
			
		||||
// making a combined work based on this library.  Thus, the terms and
 | 
			
		||||
// conditions of the GNU General Public License cover the whole
 | 
			
		||||
// combination.
 | 
			
		||||
// 
 | 
			
		||||
// As a special exception, the copyright holders of this library give you
 | 
			
		||||
// permission to link this library with independent modules to produce an
 | 
			
		||||
// executable, regardless of the license terms of these independent
 | 
			
		||||
// modules, and to copy and distribute the resulting executable under
 | 
			
		||||
// terms of your choice, provided that you also meet, for each linked
 | 
			
		||||
// independent module, the terms and conditions of the license of that
 | 
			
		||||
// module.  An independent module is a module which is not derived from
 | 
			
		||||
// or based on this library.  If you modify this library, you may extend
 | 
			
		||||
// this exception to your version of the library, but you are not
 | 
			
		||||
// obligated to do so.  If you do not wish to do so, delete this
 | 
			
		||||
// exception statement from your version.
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.SharpZipLib.Zip.Compression.Streams
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Contains the output from the Inflation process.
 | 
			
		||||
    /// We need to have a window so that we can refer backwards into the output stream
 | 
			
		||||
    /// to repeat stuff.<br/>
 | 
			
		||||
    /// Author of the original java version: John Leuner
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal class OutputWindow
 | 
			
		||||
    {
 | 
			
		||||
        #region Constants
 | 
			
		||||
        const int WindowSize = 1 << 15;
 | 
			
		||||
        const int WindowMask = WindowSize - 1;
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Instance Fields
 | 
			
		||||
        byte[] window = new byte[WindowSize]; //The window is 2^15 bytes
 | 
			
		||||
        int windowEnd;
 | 
			
		||||
        int windowFilled;
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Write a byte to this output window
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="value">value to write</param>
 | 
			
		||||
        /// <exception cref="InvalidOperationException">
 | 
			
		||||
        /// if window is full
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public void Write(int value)
 | 
			
		||||
        {
 | 
			
		||||
            if (windowFilled++ == WindowSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new InvalidOperationException("Window full");
 | 
			
		||||
            }
 | 
			
		||||
            window[windowEnd++] = (byte)value;
 | 
			
		||||
            windowEnd &= WindowMask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private void SlowRepeat(int repStart, int length, int distance)
 | 
			
		||||
        {
 | 
			
		||||
            while (length-- > 0)
 | 
			
		||||
            {
 | 
			
		||||
                window[windowEnd++] = window[repStart++];
 | 
			
		||||
                windowEnd &= WindowMask;
 | 
			
		||||
                repStart &= WindowMask;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Append a byte pattern already in the window itself
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="length">length of pattern to copy</param>
 | 
			
		||||
        /// <param name="distance">distance from end of window pattern occurs</param>
 | 
			
		||||
        /// <exception cref="InvalidOperationException">
 | 
			
		||||
        /// If the repeated data overflows the window
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public void Repeat(int length, int distance)
 | 
			
		||||
        {
 | 
			
		||||
            if ((windowFilled += length) > WindowSize)
 | 
			
		||||
            {
 | 
			
		||||
                throw new InvalidOperationException("Window full");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int repStart = (windowEnd - distance) & WindowMask;
 | 
			
		||||
            int border = WindowSize - length;
 | 
			
		||||
            if ((repStart <= border) && (windowEnd < border))
 | 
			
		||||
            {
 | 
			
		||||
                if (length <= distance)
 | 
			
		||||
                {
 | 
			
		||||
                    System.Array.Copy(window, repStart, window, windowEnd, length);
 | 
			
		||||
                    windowEnd += length;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    // We have to copy manually, since the repeat pattern overlaps.
 | 
			
		||||
                    while (length-- > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        window[windowEnd++] = window[repStart++];
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                SlowRepeat(repStart, length, distance);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Copy from input manipulator to internal window
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="input">source of data</param>
 | 
			
		||||
        /// <param name="length">length of data to copy</param>
 | 
			
		||||
        /// <returns>the number of bytes copied</returns>
 | 
			
		||||
        public int CopyStored(StreamManipulator input, int length)
 | 
			
		||||
        {
 | 
			
		||||
            length = Math.Min(Math.Min(length, WindowSize - windowFilled), input.AvailableBytes);
 | 
			
		||||
            int copied;
 | 
			
		||||
 | 
			
		||||
            int tailLen = WindowSize - windowEnd;
 | 
			
		||||
            if (length > tailLen)
 | 
			
		||||
            {
 | 
			
		||||
                copied = input.CopyBytes(window, windowEnd, tailLen);
 | 
			
		||||
                if (copied == tailLen)
 | 
			
		||||
                {
 | 
			
		||||
                    copied += input.CopyBytes(window, 0, length - tailLen);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                copied = input.CopyBytes(window, windowEnd, length);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            windowEnd = (windowEnd + copied) & WindowMask;
 | 
			
		||||
            windowFilled += copied;
 | 
			
		||||
            return copied;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Copy dictionary to window
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="dictionary">source dictionary</param>
 | 
			
		||||
        /// <param name="offset">offset of start in source dictionary</param>
 | 
			
		||||
        /// <param name="length">length of dictionary</param>
 | 
			
		||||
        /// <exception cref="InvalidOperationException">
 | 
			
		||||
        /// If window isnt empty
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public void CopyDict(byte[] dictionary, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            if (dictionary == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException("dictionary");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (windowFilled > 0)
 | 
			
		||||
            {
 | 
			
		||||
                throw new InvalidOperationException();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (length > WindowSize)
 | 
			
		||||
            {
 | 
			
		||||
                offset += length - WindowSize;
 | 
			
		||||
                length = WindowSize;
 | 
			
		||||
            }
 | 
			
		||||
            System.Array.Copy(dictionary, offset, window, 0, length);
 | 
			
		||||
            windowEnd = length & WindowMask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get remaining unfilled space in window
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>Number of bytes left in window</returns>
 | 
			
		||||
        public int GetFreeSpace()
 | 
			
		||||
        {
 | 
			
		||||
            return WindowSize - windowFilled;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get bytes available for output in window
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>Number of bytes filled</returns>
 | 
			
		||||
        public int GetAvailable()
 | 
			
		||||
        {
 | 
			
		||||
            return windowFilled;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Copy contents of window to output
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="output">buffer to copy to</param>
 | 
			
		||||
        /// <param name="offset">offset to start at</param>
 | 
			
		||||
        /// <param name="len">number of bytes to count</param>
 | 
			
		||||
        /// <returns>The number of bytes copied</returns>
 | 
			
		||||
        /// <exception cref="InvalidOperationException">
 | 
			
		||||
        /// If a window underflow occurs
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public int CopyOutput(byte[] output, int offset, int len)
 | 
			
		||||
        {
 | 
			
		||||
            int copyEnd = windowEnd;
 | 
			
		||||
            if (len > windowFilled)
 | 
			
		||||
            {
 | 
			
		||||
                len = windowFilled;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                copyEnd = (windowEnd - windowFilled + len) & WindowMask;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int copied = len;
 | 
			
		||||
            int tailLen = len - copyEnd;
 | 
			
		||||
 | 
			
		||||
            if (tailLen > 0)
 | 
			
		||||
            {
 | 
			
		||||
                System.Array.Copy(window, WindowSize - tailLen, output, offset, tailLen);
 | 
			
		||||
                offset += tailLen;
 | 
			
		||||
                len = copyEnd;
 | 
			
		||||
            }
 | 
			
		||||
            System.Array.Copy(window, copyEnd - len, output, offset, len);
 | 
			
		||||
            windowFilled -= copied;
 | 
			
		||||
            if (windowFilled < 0)
 | 
			
		||||
            {
 | 
			
		||||
                throw new InvalidOperationException();
 | 
			
		||||
            }
 | 
			
		||||
            return copied;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Reset by clearing window so <see cref="GetAvailable">GetAvailable</see> returns 0
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Reset()
 | 
			
		||||
        {
 | 
			
		||||
            windowFilled = windowEnd = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,318 @@
 | 
			
		||||
// StreamManipulator.cs
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2001 Mike Krueger
 | 
			
		||||
//
 | 
			
		||||
// This file was translated from java, it was part of the GNU Classpath
 | 
			
		||||
// Copyright (C) 2001 Free Software Foundation, Inc.
 | 
			
		||||
//
 | 
			
		||||
// This program is free software; you can redistribute it and/or
 | 
			
		||||
// modify it under the terms of the GNU General Public License
 | 
			
		||||
// as published by the Free Software Foundation; either version 2
 | 
			
		||||
// of the License, or (at your option) any later version.
 | 
			
		||||
//
 | 
			
		||||
// This program is distributed in the hope that it will be useful,
 | 
			
		||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
// GNU General Public License for more details.
 | 
			
		||||
//
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with this program; if not, write to the Free Software
 | 
			
		||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 | 
			
		||||
//
 | 
			
		||||
// Linking this library statically or dynamically with other modules is
 | 
			
		||||
// making a combined work based on this library.  Thus, the terms and
 | 
			
		||||
// conditions of the GNU General Public License cover the whole
 | 
			
		||||
// combination.
 | 
			
		||||
// 
 | 
			
		||||
// As a special exception, the copyright holders of this library give you
 | 
			
		||||
// permission to link this library with independent modules to produce an
 | 
			
		||||
// executable, regardless of the license terms of these independent
 | 
			
		||||
// modules, and to copy and distribute the resulting executable under
 | 
			
		||||
// terms of your choice, provided that you also meet, for each linked
 | 
			
		||||
// independent module, the terms and conditions of the license of that
 | 
			
		||||
// module.  An independent module is a module which is not derived from
 | 
			
		||||
// or based on this library.  If you modify this library, you may extend
 | 
			
		||||
// this exception to your version of the library, but you are not
 | 
			
		||||
// obligated to do so.  If you do not wish to do so, delete this
 | 
			
		||||
// exception statement from your version.
 | 
			
		||||
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace PdfSharp.SharpZipLib.Zip.Compression.Streams
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// This class allows us to retrieve a specified number of bits from
 | 
			
		||||
    /// the input buffer, as well as copy big byte blocks.
 | 
			
		||||
    ///
 | 
			
		||||
    /// It uses an int buffer to store up to 31 bits for direct
 | 
			
		||||
    /// manipulation.  This guarantees that we can get at least 16 bits,
 | 
			
		||||
    /// but we only need at most 15, so this is all safe.
 | 
			
		||||
    ///
 | 
			
		||||
    /// There are some optimizations in this class, for example, you must
 | 
			
		||||
    /// never peek more than 8 bits more than needed, and you must first
 | 
			
		||||
    /// peek bits before you may drop them.  This is not a general purpose
 | 
			
		||||
    /// class but optimized for the behaviour of the Inflater.
 | 
			
		||||
    ///
 | 
			
		||||
    /// Authors of the original java version: John Leuner, Jochen Hoenicke
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal class StreamManipulator
 | 
			
		||||
    {
 | 
			
		||||
        #region Constructors
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Constructs a default StreamManipulator with all buffers empty
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public StreamManipulator()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get the next sequence of bits but don't increase input pointer.  bitCount must be
 | 
			
		||||
        /// less or equal 16 and if this call succeeds, you must drop
 | 
			
		||||
        /// at least n - 8 bits in the next call.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="bitCount">The number of bits to peek.</param>
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// the value of the bits, or -1 if not enough bits available.  */
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        public int PeekBits(int bitCount)
 | 
			
		||||
        {
 | 
			
		||||
            if (bitsInBuffer_ < bitCount)
 | 
			
		||||
            {
 | 
			
		||||
                if (windowStart_ == windowEnd_)
 | 
			
		||||
                {
 | 
			
		||||
                    return -1; // ok
 | 
			
		||||
                }
 | 
			
		||||
                buffer_ |= (uint)((window_[windowStart_++] & 0xff |
 | 
			
		||||
                                 (window_[windowStart_++] & 0xff) << 8) << bitsInBuffer_);
 | 
			
		||||
                bitsInBuffer_ += 16;
 | 
			
		||||
            }
 | 
			
		||||
            return (int)(buffer_ & ((1 << bitCount) - 1));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Drops the next n bits from the input.  You should have called PeekBits
 | 
			
		||||
        /// with a bigger or equal n before, to make sure that enough bits are in
 | 
			
		||||
        /// the bit buffer.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="bitCount">The number of bits to drop.</param>
 | 
			
		||||
        public void DropBits(int bitCount)
 | 
			
		||||
        {
 | 
			
		||||
            buffer_ >>= bitCount;
 | 
			
		||||
            bitsInBuffer_ -= bitCount;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets the next n bits and increases input pointer.  This is equivalent
 | 
			
		||||
        /// to <see cref="PeekBits"/> followed by <see cref="DropBits"/>, except for correct error handling.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="bitCount">The number of bits to retrieve.</param>
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// the value of the bits, or -1 if not enough bits available.
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        public int GetBits(int bitCount)
 | 
			
		||||
        {
 | 
			
		||||
            int bits = PeekBits(bitCount);
 | 
			
		||||
            if (bits >= 0)
 | 
			
		||||
            {
 | 
			
		||||
                DropBits(bitCount);
 | 
			
		||||
            }
 | 
			
		||||
            return bits;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets the number of bits available in the bit buffer.  This must be
 | 
			
		||||
        /// only called when a previous PeekBits() returned -1.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// the number of bits available.
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        public int AvailableBits
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return bitsInBuffer_;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets the number of bytes available.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// The number of bytes available.
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        public int AvailableBytes
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return windowEnd_ - windowStart_ + (bitsInBuffer_ >> 3);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Skips to the next byte boundary.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void SkipToByteBoundary()
 | 
			
		||||
        {
 | 
			
		||||
            buffer_ >>= (bitsInBuffer_ & 7);
 | 
			
		||||
            bitsInBuffer_ &= ~7;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns true when SetInput can be called
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IsNeedingInput
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return windowStart_ == windowEnd_;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Copies bytes from input buffer to output buffer starting
 | 
			
		||||
        /// at output[offset].  You have to make sure, that the buffer is
 | 
			
		||||
        /// byte aligned.  If not enough bytes are available, copies fewer
 | 
			
		||||
        /// bytes.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="output">
 | 
			
		||||
        /// The buffer to copy bytes to.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="offset">
 | 
			
		||||
        /// The offset in the buffer at which copying starts
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <param name="length">
 | 
			
		||||
        /// The length to copy, 0 is allowed.
 | 
			
		||||
        /// </param>
 | 
			
		||||
        /// <returns>
 | 
			
		||||
        /// The number of bytes copied, 0 if no bytes were available.
 | 
			
		||||
        /// </returns>
 | 
			
		||||
        /// <exception cref="ArgumentOutOfRangeException">
 | 
			
		||||
        /// Length is less than zero
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        /// <exception cref="InvalidOperationException">
 | 
			
		||||
        /// Bit buffer isnt byte aligned
 | 
			
		||||
        /// </exception>
 | 
			
		||||
        public int CopyBytes(byte[] output, int offset, int length)
 | 
			
		||||
        {
 | 
			
		||||
            if (length < 0)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentOutOfRangeException("length");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ((bitsInBuffer_ & 7) != 0)
 | 
			
		||||
            {
 | 
			
		||||
                // bits_in_buffer may only be 0 or a multiple of 8
 | 
			
		||||
                throw new InvalidOperationException("Bit buffer is not byte aligned!");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int count = 0;
 | 
			
		||||
            while ((bitsInBuffer_ > 0) && (length > 0))
 | 
			
		||||
            {
 | 
			
		||||
                output[offset++] = (byte)buffer_;
 | 
			
		||||
                buffer_ >>= 8;
 | 
			
		||||
                bitsInBuffer_ -= 8;
 | 
			
		||||
                length--;
 | 
			
		||||
                count++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (length == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return count;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int avail = windowEnd_ - windowStart_;
 | 
			
		||||
            if (length > avail)
 | 
			
		||||
            {
 | 
			
		||||
                length = avail;
 | 
			
		||||
            }
 | 
			
		||||
            System.Array.Copy(window_, windowStart_, output, offset, length);
 | 
			
		||||
            windowStart_ += length;
 | 
			
		||||
 | 
			
		||||
            if (((windowStart_ - windowEnd_) & 1) != 0)
 | 
			
		||||
            {
 | 
			
		||||
                // We always want an even number of bytes in input, see peekBits
 | 
			
		||||
                buffer_ = (uint)(window_[windowStart_++] & 0xff);
 | 
			
		||||
                bitsInBuffer_ = 8;
 | 
			
		||||
            }
 | 
			
		||||
            return count + length;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Resets state and empties internal buffers
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Reset()
 | 
			
		||||
        {
 | 
			
		||||
            buffer_ = 0;
 | 
			
		||||
            windowStart_ = windowEnd_ = bitsInBuffer_ = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Add more input for consumption.
 | 
			
		||||
        /// Only call when IsNeedingInput returns true
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="buffer">data to be input</param>
 | 
			
		||||
        /// <param name="offset">offset of first byte of input</param>
 | 
			
		||||
        /// <param name="count">number of bytes of input to add.</param>
 | 
			
		||||
        public void SetInput(byte[] buffer, int offset, int count)
 | 
			
		||||
        {
 | 
			
		||||
            if (buffer == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException("buffer");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (offset < 0)
 | 
			
		||||
            {
 | 
			
		||||
#if NETCF_1_0
 | 
			
		||||
				throw new ArgumentOutOfRangeException("offset");
 | 
			
		||||
#else
 | 
			
		||||
                throw new ArgumentOutOfRangeException("offset", "Cannot be negative");
 | 
			
		||||
#endif
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (count < 0)
 | 
			
		||||
            {
 | 
			
		||||
#if NETCF_1_0
 | 
			
		||||
				throw new ArgumentOutOfRangeException("count");
 | 
			
		||||
#else
 | 
			
		||||
                throw new ArgumentOutOfRangeException("count", "Cannot be negative");
 | 
			
		||||
#endif
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (windowStart_ < windowEnd_)
 | 
			
		||||
            {
 | 
			
		||||
                throw new InvalidOperationException("Old input was not completely processed");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            int end = offset + count;
 | 
			
		||||
 | 
			
		||||
            // We want to throw an ArrayIndexOutOfBoundsException early.
 | 
			
		||||
            // Note the check also handles integer wrap around.
 | 
			
		||||
            if ((offset > end) || (end > buffer.Length))
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentOutOfRangeException("count");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ((count & 1) != 0)
 | 
			
		||||
            {
 | 
			
		||||
                // We always want an even number of bytes in input, see PeekBits
 | 
			
		||||
                buffer_ |= (uint)((buffer[offset++] & 0xff) << bitsInBuffer_);
 | 
			
		||||
                bitsInBuffer_ += 8;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            window_ = buffer;
 | 
			
		||||
            windowStart_ = offset;
 | 
			
		||||
            windowEnd_ = end;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #region Instance Fields
 | 
			
		||||
        private byte[] window_;
 | 
			
		||||
        private int windowStart_;
 | 
			
		||||
        private int windowEnd_;
 | 
			
		||||
 | 
			
		||||
        private uint buffer_;
 | 
			
		||||
        private int bitsInBuffer_;
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user