Sfoglia il codice sorgente

Zlib compression uses BouncyCastle as a fallback if BCL does not support. (#1453)

Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
Scott Xu 1 anno fa
parent
commit
c614f54f0a

+ 1 - 1
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<span></span>@openssh.com (.NET 6 and higher)
+* zlib<span></span>@openssh.com
 
 ## Framework Support
 

+ 2 - 0
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:

+ 24 - 3
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 @@ namespace Renci.SshNet.Compression
             _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
         }
 
         /// <inheritdoc/>
@@ -61,6 +74,7 @@ namespace Renci.SshNet.Compression
         /// <inheritdoc/>
         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 @@ namespace Renci.SshNet.Compression
             _decompressorStream.SetLength(0);
 
             return outputStream.ToArray();
+#else
+            _decompressorStream.SetLength(0);
+
+            _decompressor.Write(data, offset, length);
+            _decompressor.Flush();
+
+            return _decompressorStream.ToArray();
+#endif
         }
 
         /// <summary>
@@ -106,4 +128,3 @@ namespace Renci.SshNet.Compression
         }
     }
 }
-#endif

+ 1 - 3
src/Renci.SshNet/Compression/ZlibOpenSsh.cs

@@ -1,5 +1,4 @@
-#if NET6_0_OR_GREATER
-namespace Renci.SshNet.Compression
+namespace Renci.SshNet.Compression
 {
     /// <summary>
     /// Represents the "zlib@openssh.com" compression algorithm.
@@ -21,4 +20,3 @@ namespace Renci.SshNet.Compression
         }
     }
 }
-#endif

+ 0 - 2
src/Renci.SshNet/ConnectionInfo.cs

@@ -426,9 +426,7 @@ namespace Renci.SshNet
             CompressionAlgorithms = new Dictionary<string, Func<Compressor>>
                 {
                     { "none", null },
-#if NET6_0_OR_GREATER
                     { "zlib@openssh.com", () => new ZlibOpenSsh() },
-#endif
                 };
 
             ChannelRequests = new Dictionary<string, RequestInfo>

+ 0 - 2
test/Renci.SshNet.IntegrationTests/CompressionTests.cs

@@ -19,13 +19,11 @@ namespace Renci.SshNet.IntegrationTests
             DoTest(new KeyValuePair<string, Func<Compressor>>("none", null));
         }
 
-#if NET6_0_OR_GREATER
         [TestMethod]
         public void ZlibOpenSsh()
         {
             DoTest(new KeyValuePair<string, Func<Compressor>>("zlib@openssh.com", () => new ZlibOpenSsh()));
         }
-#endif
 
         private void DoTest(KeyValuePair<string, Func<Compressor>> compressor)
         {