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)
{