using System.IO; #if NET6_0_OR_GREATER using System.IO.Compression; #else using Org.BouncyCastle.Utilities.Zlib; #endif namespace Renci.SshNet.Compression { /// /// Represents the "zlib" compression algorithm. /// #pragma warning disable CA1724 // Type names should not match namespaces public class Zlib : Compressor #pragma warning restore CA1724 // Type names should not match namespaces { #if NET6_0_OR_GREATER private readonly ZLibStream _compressor; private readonly ZLibStream _decompressor; #else private readonly ZOutputStream _compressor; private readonly ZOutputStream _decompressor; #endif private MemoryStream _compressorStream; private MemoryStream _decompressorStream; private bool _isDisposed; /// /// Initializes a new instance of the class. /// public Zlib() : this(delayedCompression: false) { } /// /// Initializes a new instance of the class. /// /// /// /// protected Zlib(bool delayedCompression) : base(delayedCompression) { _compressorStream = new MemoryStream(); _decompressorStream = new MemoryStream(); #if NET6_0_OR_GREATER _compressor = new ZLibStream(_compressorStream, CompressionMode.Compress); _decompressor = new ZLibStream(_decompressorStream, CompressionMode.Decompress); #else _compressor = new ZOutputStream(_compressorStream, level: JZlib.Z_DEFAULT_COMPRESSION) { FlushMode = JZlib.Z_PARTIAL_FLUSH }; _decompressor = new ZOutputStream(_decompressorStream) { FlushMode = JZlib.Z_PARTIAL_FLUSH }; #endif } /// public override string Name { get { return "zlib"; } } /// protected override byte[] CompressCore(byte[] data, int offset, int length) { _compressorStream.SetLength(0); _compressor.Write(data, offset, length); _compressor.Flush(); return _compressorStream.ToArray(); } /// protected override byte[] DecompressCore(byte[] data, int offset, int length) { #if NET6_0_OR_GREATER _decompressorStream.Write(data, offset, length); _decompressorStream.Position = 0; using var outputStream = new MemoryStream(); _decompressor.CopyTo(outputStream); _decompressorStream.SetLength(0); return outputStream.ToArray(); #else _decompressorStream.SetLength(0); _decompressor.Write(data, offset, length); _decompressor.Flush(); return _decompressorStream.ToArray(); #endif } /// /// Releases unmanaged and - optionally - managed resources. /// /// to release both managed and unmanaged resources; to release only unmanaged resources. protected override void Dispose(bool disposing) { base.Dispose(disposing); if (_isDisposed) { return; } if (disposing) { var compressorStream = _compressorStream; if (compressorStream != null) { compressorStream.Dispose(); _compressorStream = null; } var decompressorStream = _decompressorStream; if (decompressorStream != null) { decompressorStream.Dispose(); _decompressorStream = null; } _isDisposed = true; } } } }