From 377eaeedb12ae966cc093e698553f9f92268b8f6 Mon Sep 17 00:00:00 2001 From: Scott Xu Date: Sun, 21 Jul 2024 23:54:15 +0800 Subject: [PATCH] Zlib compression uses BouncyCastle as a fallback if BCL does not support. --- README.md | 2 +- appveyor.yml | 2 ++ src/Renci.SshNet/Compression/Zlib.cs | 27 ++++++++++++++++--- src/Renci.SshNet/Compression/ZlibOpenSsh.cs | 4 +-- src/Renci.SshNet/ConnectionInfo.cs | 2 -- .../CompressionTests.cs | 2 -- 6 files changed, 28 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index a6c09ecc8..d76d60124 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Private keys can be encrypted using one of the following cipher methods: **SSH.NET** supports the following compression algorithms: * none (default) -* zlib@openssh.com (.NET 6 and higher) +* zlib@openssh.com ## Framework Support diff --git a/appveyor.yml b/appveyor.yml index f8b7db9fa..1a9d73906 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -21,12 +21,14 @@ for: - echo build - dotnet build -f net8.0 -c Debug test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj - dotnet build -f net8.0 -c Debug test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj + - dotnet build -f net48 -c Debug test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj test_script: - sh: echo "Run unit tests" - sh: dotnet test -f net8.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_unit_test_net_8_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_unit_test_net_8_coverage.xml test/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj - sh: echo "Run integration tests" - sh: dotnet test -f net8.0 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_integration_test_net_8_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_integration_test_net_8_coverage.xml test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj + - sh: dotnet test -f net48 -c Debug --no-restore --no-build --results-directory artifacts --logger Appveyor --logger "console;verbosity=normal" --logger "liquid.md;LogFileName=linux_integration_test_net_48_report.md" -p:CollectCoverage=true -p:CoverletOutputFormat=cobertura -p:CoverletOutput=../../artifacts/linux_integration_test_net_48_coverage.xml --filter Name~Zlib test/Renci.SshNet.IntegrationTests/Renci.SshNet.IntegrationTests.csproj - matrix: diff --git a/src/Renci.SshNet/Compression/Zlib.cs b/src/Renci.SshNet/Compression/Zlib.cs index 20346c900..f82015de1 100644 --- a/src/Renci.SshNet/Compression/Zlib.cs +++ b/src/Renci.SshNet/Compression/Zlib.cs @@ -1,6 +1,9 @@ -#if NET6_0_OR_GREATER -using System.IO; +using System.IO; +#if NET6_0_OR_GREATER using System.IO.Compression; +#else +using Org.BouncyCastle.Utilities.Zlib; +#endif namespace Renci.SshNet.Compression { @@ -11,8 +14,13 @@ namespace Renci.SshNet.Compression 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; @@ -37,8 +45,13 @@ protected Zlib(bool 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 } /// @@ -61,6 +74,7 @@ protected override byte[] CompressCore(byte[] data, int offset, int length) /// protected override byte[] DecompressCore(byte[] data, int offset, int length) { +#if NET6_0_OR_GREATER _decompressorStream.Write(data, offset, length); _decompressorStream.Position = 0; @@ -70,6 +84,14 @@ protected override byte[] DecompressCore(byte[] data, int offset, int length) _decompressorStream.SetLength(0); return outputStream.ToArray(); +#else + _decompressorStream.SetLength(0); + + _decompressor.Write(data, offset, length); + _decompressor.Flush(); + + return _decompressorStream.ToArray(); +#endif } /// @@ -106,4 +128,3 @@ protected override void Dispose(bool disposing) } } } -#endif diff --git a/src/Renci.SshNet/Compression/ZlibOpenSsh.cs b/src/Renci.SshNet/Compression/ZlibOpenSsh.cs index 02bea40bc..1df468097 100644 --- a/src/Renci.SshNet/Compression/ZlibOpenSsh.cs +++ b/src/Renci.SshNet/Compression/ZlibOpenSsh.cs @@ -1,5 +1,4 @@ -#if NET6_0_OR_GREATER -namespace Renci.SshNet.Compression +namespace Renci.SshNet.Compression { /// /// Represents the "zlib@openssh.com" compression algorithm. @@ -21,4 +20,3 @@ public override string Name } } } -#endif diff --git a/src/Renci.SshNet/ConnectionInfo.cs b/src/Renci.SshNet/ConnectionInfo.cs index 4c2e9b375..f026c94da 100644 --- a/src/Renci.SshNet/ConnectionInfo.cs +++ b/src/Renci.SshNet/ConnectionInfo.cs @@ -426,9 +426,7 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy CompressionAlgorithms = new Dictionary> { { "none", null }, -#if NET6_0_OR_GREATER { "zlib@openssh.com", () => new ZlibOpenSsh() }, -#endif }; ChannelRequests = new Dictionary diff --git a/test/Renci.SshNet.IntegrationTests/CompressionTests.cs b/test/Renci.SshNet.IntegrationTests/CompressionTests.cs index 68cf1b237..fbceeae12 100644 --- a/test/Renci.SshNet.IntegrationTests/CompressionTests.cs +++ b/test/Renci.SshNet.IntegrationTests/CompressionTests.cs @@ -19,13 +19,11 @@ public void None() DoTest(new KeyValuePair>("none", null)); } -#if NET6_0_OR_GREATER [TestMethod] public void ZlibOpenSsh() { DoTest(new KeyValuePair>("zlib@openssh.com", () => new ZlibOpenSsh())); } -#endif private void DoTest(KeyValuePair> compressor) {