|  | @@ -1,17 +1,46 @@
 | 
	
		
			
				|  |  |  using System.Collections.Generic;
 | 
	
		
			
				|  |  |  using Renci.SshNet.Security;
 | 
	
		
			
				|  |  | +using System.IO;
 | 
	
		
			
				|  |  | +using System;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  namespace Renci.SshNet.Compression
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      /// <summary>
 | 
	
		
			
				|  |  |      /// Represents base class for compression algorithm implementation
 | 
	
		
			
				|  |  |      /// </summary>
 | 
	
		
			
				|  |  | -    public abstract class Compressor : Algorithm
 | 
	
		
			
				|  |  | +    public abstract class Compressor : Algorithm, IDisposable
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | +        private readonly ZlibStream _compressor;
 | 
	
		
			
				|  |  | +        private readonly ZlibStream _decompressor;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private MemoryStream _compressorStream;
 | 
	
		
			
				|  |  | +        private MemoryStream _decompressorStream;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Gets or sets a value indicating whether compression is active.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <value>
 | 
	
		
			
				|  |  | +        ///   <c>true</c> if compression is active; otherwise, <c>false</c>.
 | 
	
		
			
				|  |  | +        /// </value>
 | 
	
		
			
				|  |  | +        protected bool IsActive { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Gets the session.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          protected Session Session { get; private set; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Initializes a new instance of the <see cref="Compressor"/> class.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public Compressor()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            this._compressorStream = new MemoryStream();
 | 
	
		
			
				|  |  | +            this._decompressorStream = new MemoryStream();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            this._compressor = new ZlibStream(this._compressorStream, CompressionMode.Compress);
 | 
	
		
			
				|  |  | +            this._decompressor = new ZlibStream(this._decompressorStream, CompressionMode.Decompress);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Initializes the algorithm
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
	
		
			
				|  | @@ -26,13 +55,97 @@ namespace Renci.SshNet.Compression
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          /// <param name="data">Data to compress.</param>
 | 
	
		
			
				|  |  |          /// <returns>Compressed data</returns>
 | 
	
		
			
				|  |  | -        public abstract byte[] Compress(byte[] data);
 | 
	
		
			
				|  |  | +        public virtual byte[] Compress(byte[] data)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (!this.IsActive)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return data;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            this._compressorStream.SetLength(0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            this._compressor.Write(data, 0, data.Length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return this._compressorStream.ToArray();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Decompresses the specified data.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
		
			
				|  |  |          /// <param name="data">Compressed data.</param>
 | 
	
		
			
				|  |  |          /// <returns>Decompressed data.</returns>
 | 
	
		
			
				|  |  | -        public abstract byte[] Decompress(byte[] data);
 | 
	
		
			
				|  |  | +        public virtual byte[] Decompress(byte[] data)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (!this.IsActive)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return data;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            this._decompressorStream.SetLength(0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            this._decompressor.Write(data, 0, data.Length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return this._decompressorStream.ToArray();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #region IDisposable Members
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private bool _isDisposed = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public void Dispose()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            Dispose(true);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            GC.SuppressFinalize(this);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Releases unmanaged and - optionally - managed resources
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged ResourceMessages.</param>
 | 
	
		
			
				|  |  | +        protected virtual void Dispose(bool disposing)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            // Check to see if Dispose has already been called.
 | 
	
		
			
				|  |  | +            if (!this._isDisposed)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // If disposing equals true, dispose all managed
 | 
	
		
			
				|  |  | +                // and unmanaged ResourceMessages.
 | 
	
		
			
				|  |  | +                if (disposing)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    // Dispose managed ResourceMessages.
 | 
	
		
			
				|  |  | +                    if (this._compressorStream != null)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        this._compressorStream.Dispose();
 | 
	
		
			
				|  |  | +                        this._compressorStream = null;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    if (this._decompressorStream != null)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        this._decompressorStream.Dispose();
 | 
	
		
			
				|  |  | +                        this._decompressorStream = null;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // Note disposing has been done.
 | 
	
		
			
				|  |  | +                this._isDisposed = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Releases unmanaged resources and performs other cleanup operations before the
 | 
	
		
			
				|  |  | +        /// <see cref="SshCommand"/> is reclaimed by garbage collection.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        ~Compressor()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            // Do not re-create Dispose clean-up code here.
 | 
	
		
			
				|  |  | +            // Calling Dispose(false) is optimal in terms of
 | 
	
		
			
				|  |  | +            // readability and maintainability.
 | 
	
		
			
				|  |  | +            Dispose(false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        #endregion
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |